C# Socket编程 服务端与客户端(四) 异步服务端

    xiaoxiao2021-11-29  31

    异步编写Socket服务端

    注意事项与三中的异步客户端类似,不过新加了几点,主要是流程控制方面。

    1.Listen里的数字为pending的连接数,而不能控制能够连接的数量。因为是异步的,所以一有连接马上调用回调函数,在End操作里将pending中取出,所以即使listen给出的数字很小,只要End操作足够及时,能够同时处理很多连接。

    2.通过一个循环控制不断地BeginAccept,使用了信号对象,使当一个Begin被End的时候,马上会有一个新的Begin供之后的连接使用。

    3.在BeginReceive中,每当客户端有数据发送过来的时候,就会触发readCallBack回调函数,用一个End处理它,需要注意的是,当客户端关闭的时候,也会触发一次回调,但是此时数据为0。所以只在数据大于0的地方重新BeginReceive,以保证总是有一个Begin供之后客户端发送过来的数据使用。

    class asyncChange { private static Socket listener; [ThreadStatic] public static ManualResetEvent allDone; public static bool _isRunning = true; public const int _bufferSize = 1024; public const int _port = 3800; public static int cus = 1; private static object async = new object(); class StateObject { public Socket workSocket = null; public byte[] buffer = new byte[_bufferSize]; public StringBuilder sb = new StringBuilder(); } class AcceptObject { public Socket listener = null; public ManualResetEvent allDone = null; } public void Start() { IPEndPoint localIPE = new IPEndPoint(IPAddress.Any, _port); listener = new Socket(localIPE.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); listener.Bind(localIPE); //异步中每有一个连接过来时直接调用回调函数,所以pendind的连接数始终不会很大,即使是1也能应对很多连接。注意listen是pending的连接数,而不是已经连接的数量。 listener.Listen(1000); while (_isRunning) { allDone = null; allDone = new ManualResetEvent(false); AcceptObject so = new AcceptObject(); so.allDone = allDone; so.listener = listener; so.allDone.Reset(); so.listener.BeginAccept(new AsyncCallback(acceptCallBack), so); so.allDone.WaitOne(); } listener.Close(); } public static void acceptCallBack(IAsyncResult ar) { AcceptObject so = (AcceptObject)ar.AsyncState; Socket listener = (Socket)so.listener; if (listener != null) { Socket handler = listener.EndAccept(ar); so.allDone.Set(); lock (async) { Console.WriteLine($"customer No: {cus}"); cus++; } StateObject state = new StateObject(); state.workSocket = handler; state.workSocket.BeginReceive(state.buffer, 0, _bufferSize, SocketFlags.None, new AsyncCallback(readCalllBack), state); } } static void readCalllBack(IAsyncResult ar) { StateObject state = (StateObject)ar.AsyncState; Socket handler = state.workSocket; int read = handler.EndReceive(ar); if (read > 0) { state.sb.Append(Encoding.UTF8.GetString(state.buffer, 0, read)); Console.WriteLine(state.sb); //成功读取后,继续接收 StateObject newState = new StateObject(); newState.workSocket = handler; handler.BeginReceive(newState.buffer, 0, _bufferSize, SocketFlags.None, new AsyncCallback(readCalllBack), newState); } else { handler.Close(); Console.WriteLine("customer has closed his socket!"); } } } 参考: MSDN的Socket类

    转载请注明原文地址: https://ju.6miu.com/read-678589.html

    最新回复(0)