WinSocket模型的探讨——漫谈

时间:2021-07-26 00:07:43

SOCKET有两种模式——阻塞和非阻塞。

如果使用了阻塞,在某个时间点如果出现了网络问题,一边调用recv接收不到数据的时候,那就会导致程序挂在那里!对于这个问题有两种解决的方法:一是保证使用的环境永远不会出现这种情况,二是使用多线程(就算出现了阻塞的情况也就是线程挂了,主线程还是生龙活虎的)。

如果使用非阻塞的SOCKET,我们需要不断的去轮询看recv/send函数是否成功,如果不成功,我们采取等待或者是其他的策略,这种轮询的做法对任何程序来说都是不好的(没效率,除非万不得已)。试想一下,判断什么时候有东西收和可写应该不是我们的事情,应该是WINDOWS的事情!!WINSOCK是MS提供的网络编程接口,什么时候有东西要收就MS底层的驱动最清楚了(什么时候能发送也一样是MS最清楚),所以就有了WINDOWS的SOCKET模型!我们调用select,实际上就是让MS帮我们选择,什么时候应该能发和能收,而不是盲目的去轮询。隐喻:就象有一个信箱,什么时候有信来不是你最清楚的,而是邮递员最清楚。如果你不停的跑去查看信箱,那你的效率肯定就是很低的(你就像是CPU)。但如果换成邮递员来的时候,给你敲个钟,然后你再下来拿信的话,这种效率就高多了!!你的其他时间就可以做其他的事情了。邮递员就是MS提供的SELECT函数!!

但是我们的程序里一样要不停的以循环的方式调用SELECT函数,但是这个循环是能保证效率的,因为有事件的时候才干,没事件的时候就不动。所以这个循环我们可以用一个线程来做,不用担心这个线程会占用我们的CPU时间。

其实对于几种的SOCKET模型的原理都是一样的,就是什么时候有事件来了,开工了!!而这个事件是MS通知你的!!想一下,WSAASYNCSELECT不就是在MS检测到有事可干的时候通过WINDOWS的消息机制通知你吗?而WSAEVENTSELECT则是通过事件的方式去通知你,重叠IO不也就提供了事件和完成例程(在有事可干的时候,我会调用你提供的完成例程!)的方式吗?而完成端口就是能够根据CPU的个数来开线程(所以是Scalable的),它是通过你调用 GetQueuedCompletionStatus 来通知你的!和SELECT不有点异曲同工吗?

WINDOWS要达到通知你的目的,肯定要给你提供某些接口,遵守某些规定来使用,至于它内部是开线程轮询、还是事件方式,还是一些我没法理解的高深算法等,我们就不用管了! 

这里就随便说了点,在下面的几篇文章中我会更深入的探讨!

WinSocket模型的探讨——select模型

WinSocket模型的探讨——WSAAsyncSelect模型

WinSocket模型的探讨——WSAEventSelect模型

WinSocket模型的探讨——重叠IO模型

WinSocket模型的探讨——完成端口模型