扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
今天,我们就来讨论一下如何用异步Socket开发网络应用。在此之前我们先讨论两个问题。
一、异步Socket是如何工作的:
那异步Socket是如何工作的呢?我以接收一条消息来说明这个问题。首先,程序向系统投递一个接收数据的请求,并为其指定一个数据缓冲区和回调函数,回调函数用来指示当数据到达后将如何处理,然后我们的程序继续执行下去,当有数据到达的时候,系统将数据读入缓冲区,并执行回调函数,处理这条消息。我们并不需要关心这条消息何时到达。
二、什么情况下我们用异步Socket:
有些人认为,异步Socket的性能比同步Socket的性能高很多,应该在各种环境下都用异步Socket,其实不然。在某些环境下面。异步反到比同步的性能低,那么在哪些情况下会这样呢?
1、客户端Socket。
2、服务端连接数比较少。
3、连接数很多,但都是短连接。
在这些环境下,我们用同步Socket不但可以简化代码,而且性能并不会比异步Socket低。但在服务端连接比较多而且是长连接的情况下,我们就要使用异步Socket。
现在我们来看看如何用异步Socket编程。
首先,我们要建立一个Socket用来监听:
以下是引用片段: Socket _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint localEP = new IPEndPoint(_address, _port); _listener.Bind(localEP); _listener.Listen(100); |
然后创建一个线程来处理客户端连接请求:
以下是引用片段: Thread _acceptWorkThread = new Thread(AcceptWorkThread); _acceptWorkThread.Start(); private void AcceptWorkThread() ...{ while (_isListener) ...{ UserInfo info = new UserInfo();//这个UserInfo是用来保存客户信息的。 info.socket = socket; Socket socket = _listener.Accept(); //这里进行其它处理。 socket.BeginReceive(info.Buffer, 0, info.Buffer.Length, SocketFlags.None, ReceiveCallBack, info);//这里向系统投递一个接收信息的请求,并为其指定ReceiveCallBack做为回调函数 } } 我们再来看看回调函数的定义: private void ReceiveCallBack(IAsyncResult ar) ...{ UserInfo info = (UserInfo)ar.AsyncState; Socket handler = info.socket; int readCount = 0; try ...{ readCount = handler.EndReceive(ar);//调用这个函数来结束本次接收并返回接收到的数据长度。 } catch (SocketException)//出现Socket异常就关闭连接 ...{ CloseSocket(info);//这个函数用来关闭客户端连接 return; } catch ...{ } if (readCount > 0) ...{ byte[] buffer = new byte[readCount]; Buffer.BlockCopy(info.Buffer, 0, buffer, 0, readCount); Analyzer(info, buffer);//这个函数用来处理接收到的信息。 try ...{ handler.BeginReceive(info.Buffer, 0, info.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), info);//向系统投递下一个接收请求 } catch (SocketException) //出现Socket异常就关闭连接 ...{ CloseSocket(info); } catch ...{ } } else //如果接收到0字节的数据说明客户端关闭了Socket,那我们也要关闭Socket ...{ CloseSocket(info); } }接下来我们看看如何发送数据给客户端: public void Send(Socket socket, byte message) ...{ try ...{ info.socket.BeginSend(message, 0, _byte.Length, SocketFlags.None, new AsyncCallback(SendCallBack), info);//这里向系统投递一个发送数据的请求,并指定一个回调函数。 } catch (SocketException ex) ...{ CloseSocket(info); } catch ...{ } } |
定义发送回调函数:
以下是引用片段: private void SendCallBack(IAsyncResult ar) ...{ UserInfo info = (UserInfo)ar.AsyncState; try ...{ info.socket.EndSend(ar);//调用这个函数来结束本次发送。 } catch ...{ } } |
好了,整个监听、接收、发送的过程就完成了,很简单吧。现在需要说明的是,我在这里接收客户端连接的Accept是用的同步的,我个人认为在这里用同步的会比用异步好一些。因为这样代码简单而且没有性能上的损失。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者