C#网络编程穴习之Socketasynceventargs - chunlieater/chunlifeet GitHub Wiki

使用Socketasynceventargs可以很方便的实现异步调用。而不需要自己去管理线程。线程的分配是.NET负责分配的。 大概的比喻是这样,服务器是一个办公楼,ip是地址,端口是信息进出的通道,socket是通讯工具(电话),socketasynceventargs就是接线员了。 而.NET负责的是排队,相当于一个接待窗口,接待客户端连接后者接受消息的线程分配以及先后顺序。 大概的流程如下: 服务端创建监听Sockte(一般指定ipv4类型,stream类型,tcp类型),绑定好endpoint(ip,端口),然后开启监听,并调用异步函数接受连入的客户端(liteningSocket.AcceptAsync(e),相当于对listeningSocket建立一个专门的接线员负责监听),如果这时马上就有客户端连接,则函数返回fasle,直接在该线程调用回调函数,如果这是没有客户端连入,则函数返回true,socketasynceventargs参数去.NET内核等待准备好的客户端连接,同一时间连入的客户端被自动分配给不同的线程队列排队,sockestasynceventargs从哪个线程拿到连接数据,就用哪个线程调用回调函数。

回调函数:回调函数通过socketasynceventargs拿到连入的客户端信息,并且建立相对应的服务端socket,和客户端进行点对点的通讯。(一般来说都会把服务端socket放入一个usertoken类中,在这个类里还有该socket要用到的接受数据socketasynceventargs和发送数据的socketasynceventargs等其它成员变量和成员函数。)当服务端socket设置完毕,就可以启用接收信息的异步调用serverSocket.ReceiveAsync(e), 和AcceptAsync类似,ReceiveAsync也相当于一个专门负责给serverSocket进行收信服务的接线员,如果函数返回fasle,则该线程继续执行回调函数,如果返回true,则接线员就去.NET内核的线程队列里等待准备好的信息,如果接到了信息,就用该线程调用回调函数,对接收到的数据进行处理。

也就是说,socketasynceventargs自己并不会建立新的线程,而是通过.NET内核中的线程队列取得数据,并用该线程调用回调函数。也就是说,在执行xxxAsync之后,如果返回是true,那么回调函数就是在内核分配的线程中进行的了。 至于内核怎么分配线程队列,和cpu的架构有关,几个线程队列就是几个窗口,来的数据按先后顺序排队,哪个窗口有空缺,排在前面的就自动过去递交处理,而socketasynceventargs就在这个线程窗口拿数据,并且用这个线程来调用回调函数处理数据,处理完成后,该线程被释放,新的数据又可以递交过来,等待socketasynceventargs新的获取。