using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; namespace Networking { internal sealed class SocketClient : IDisposable { private const int Receive = 1; private const int Send = 0; private bool isConnected = false; private Socket socket; private DnsEndPoint endPoint; private AutoResetEvent autoEvent = new AutoResetEvent(false); private AutoResetEvent[] autoSendReceiveEvents = new AutoResetEvent[] { new AutoResetEvent(false), new AutoResetEvent(false) }; internal SocketClient(string host, int port) { endPoint = new DnsEndPoint(host, port); socket = new Socket(AddressFamily.InterNetwork /* hostEndPoint.AddressFamily */, SocketType.Stream, ProtocolType.Tcp); } internal void Connect() { SocketAsyncEventArgs args = new SocketAsyncEventArgs(); args.UserToken = socket; args.RemoteEndPoint = endPoint; args.Completed += new EventHandler(OnConnect); socket.ConnectAsync(args); autoEvent.WaitOne(); if (args.SocketError != SocketError.Success) throw new SocketException((int)args.SocketError); } internal void Disconnect() { //socket.Close(); } #region Events private void OnConnect(object sender, SocketAsyncEventArgs e) { autoEvent.Set(); isConnected = (e.SocketError == SocketError.Success); } private void OnReceive(object sender, SocketAsyncEventArgs e) { autoSendReceiveEvents[Send].Set(); } private void OnSend(object sender, SocketAsyncEventArgs e) { autoSendReceiveEvents[Receive].Set(); if (e.SocketError == SocketError.Success) { if (e.LastOperation == SocketAsyncOperation.Send) { // Prepare receiving. Socket s = e.UserToken as Socket; byte[] response = new byte[255]; e.SetBuffer(response, 0, response.Length); e.Completed += new EventHandler(OnReceive); s.ReceiveAsync(e); } } else { ProcessError(e); } } #endregion private void ProcessError(SocketAsyncEventArgs e) { Socket s = e.UserToken as Socket; if (s.Connected) { try { s.Shutdown(SocketShutdown.Both); } catch (Exception) { } finally { if (s.Connected) s.Close(); } } throw new SocketException((int)e.SocketError); } internal String SendReceive(string message) { if (isConnected) { Byte[] bytes = Encoding.UTF8.GetBytes(message); SocketAsyncEventArgs args = new SocketAsyncEventArgs(); args.SetBuffer(bytes, 0, bytes.Length); args.UserToken = socket; args.RemoteEndPoint = endPoint; args.Completed += new EventHandler(OnSend); socket.SendAsync(args); AutoResetEvent.WaitAll(autoSendReceiveEvents); return Encoding.UTF8.GetString(args.Buffer, args.Offset, args.BytesTransferred); } else throw new SocketException((int)SocketError.NotConnected); } #region IDisposable Members public void Dispose() { autoEvent.Close(); autoSendReceiveEvents[Send].Close(); autoSendReceiveEvents[Receive].Close(); if (socket.Connected) socket.Close(); } #endregion } }