zoukankan      html  css  js  c++  java
  • Winsock工作模型 ( 转 )

    首先得弄清楚同步、异步、阻塞、非阻塞的概念。
    同步和异步是针对通讯的工作模式,阻塞和非阻塞是指socket的I/O操作。
    实际上对于socket,只存在阻塞和非阻塞,同步与异步是在程序实现上有所不同。
    以阻塞的方式执行recv函数,在没有收到数据前,此函数是不会返回的,所以这很容易执行函数的线程处于等待I/O上的数据状态,然后被挂起。非阻塞就不一样,执行recv时候不管有没有数据都立即返回,有数据时返回数据,没数据时返回错误。非阻塞可以带来程序的高效,也带来了写程序中必须注意的地方,非阻塞情况下,发送与接收数据时候,要用户自己管理自己的缓冲区,并且要记录发送与接受的位置,因为很可能发送与接受数据的任务不能一次完成,需要多次调用send和recv才可以完成。
    本来同步异步是用来表示通讯模式的,通信的同步,主要是指客户端在发送请求后,必须得在服务端有回应后才发送下一个请求。所以这个时候的所有请求将会在服务端得到同步。通信的异步,指客户端在发送请求后,不必等待服务端的回应就可以发送下一个请求,这样对于所有的请求动作来说将会在服务端得到异步,这条请求的链路就象是一个请求队列,所有的动作在这里不会得到同步的。但是个人感觉,在说到socket的同步异步时候,同步跟阻塞概念差不多,都是有了结果才返回,异步则是告诉系统我要recv数据,然后马上返回,等待数据来了后,系统跟程序说数据到了,然后程序再recv数据。引用在网上看到的比较好的描述“阻塞 block 是指,你拨通某人的电话,但是此人不在,于是你拿着电话等他回来,其间不能再用电话。同步大概和阻塞差不多。非阻塞 nonblock 是指,你拨通某人的电话,但是此人不在,于是你挂断电话,待会儿再打。至于到时候他回来没有,只有打了电话才知道。即所谓的“轮询 / poll”。异步是指,你拨通某人的电话,但是此人不在,于是你叫接电话的人告诉那人(leave a message),回来后给你打电话(call back)。”

    显然,异步要高效一些。在Winsock中实现异步的方法有很多,Winsock工作模型有下面六种
        一:select模型
        二:WSAAsyncSelect模型
        三:WSAEventSelect模型
        四:Overlapped I/O 事件通知模型
        五:Overlapped I/O 完成例程模型
        六:IOCP模型
    从一到六越来越高级,越来越高效,实现越来越复杂。曾在网上看到一些比喻用来很好的说明这些模型,在这里引用一下。

        老陈有一个在外地工作的女儿,不能经常回来,老陈和她通过信件联系。他们的信会被邮递员投递到他们的信箱里。
    一:select模型

    老陈非常想看到女儿的信。以至于他每隔10分钟就下楼检查信箱,看是否有女儿的信~~~~~
    在这种情况下,“下楼检查信箱”然后回到楼上耽误了老陈太多的时间,以至于老陈无法做其他工作。

    二:WSAAsyncSelect模型

    后来,老陈使用了微软公司的新式信箱。这种信箱非常先进,一旦信箱里有新的信件,盖茨就会给老陈打电话:喂,大爷,你有新的信件了!从此,老陈再也不必频繁上下楼检查信箱了,牙也不疼了,你瞅准了,蓝天......不是,微软~~~~~~~~

    三:WSAEventSelect模型

    后来,微软的信箱非常畅销,购买微软信箱的人以百万计数......以至于盖茨每天24小时给客户打电话,累得腰酸背痛,喝蚁力神都不好使~~~~~~
    微软改进了他们的信箱:在客户的家中添加一个附加装置,这个装置会监视客户的信箱,每当新的信件来临,此装置会发出“新信件到达”声,提醒老陈去收信。盖茨终于可以睡觉了。

    四:Overlapped I/O 事件通知模型

    后来,微软通过调查发现,老陈不喜欢上下楼收发信件,因为上下楼其实很浪费时间。于是微软再次改进他们的信箱。新式的信箱采用了更为先进的技术,只要用户告诉微软自己的家在几楼几号,新式信箱会把信件直接传送到用户的家中,然后告诉用户,你的信件已经放到你的家中了!老陈很高兴,因为他不必再亲自收发信件了!

    五:Overlapped I/O 完成例程模型

    老陈接收到新的信件后,一般的程序是:打开信封----掏出信纸----阅读信件----回复信件......为了进一步减轻用户负担,微软又开发了一种新的技术:用户只要告诉微软对信件的操作步骤,微软信箱将按照这些步骤去处理信件,不再需要用户亲自拆信/阅读/回复了!老陈终于过上了小资生活!

    六:IOCP模型

    微软信箱似乎很完美,老陈也很满意。但是在一些大公司情况却完全不同!这些大公司有数以万计的信箱,每秒钟都有数以百计的信件需要处理,以至于微软信箱经常因超负荷运转而崩溃!需要重新启动!微软不得不使出杀手锏......
    微软给每个大公司派了一名名叫“Completion Port”的超级机器人,让这个机器人去处理那些信件!


    其实,上面每种模型都有优点,要根据程序需求而适当选择合适的模型,前面三种模型效率已经比较高,实现起来难道不大,很多一般的网络程序都采用前三种模型,只有对网络要求特别高的一些服务器才会考虑用后面的那些模型。MFC中的CAsyncSocket类就是用的WSAAsyncSelect模型,电驴中也是用的这种,不过在寻找对应socket的时候进行了优化,查找更快,在GridCast中采用的是WSAEventSelect模型,等待。


    BTW:上面所说均在Windows平台下,只用WinSock才有这么多模型,在linux下,好像就只有第一种select模式,我对linux下的socket不是很了解,应该也有很多提高效率的地方。

  • 相关阅读:
    vue开发chrome扩展,数据通过storage对象获取
    Vue手动集成less预编译器
    Google Translate寻找之旅
    Javascript Range对象的学习
    Javascript Promises学习
    SublimeText 建立构建Node js系统
    We're sorry but demo3 doesn't work properly without JavaScript enabled. Please enable it to continue.
    npm安装包出现UNMET DEPENDENCY报错
    (转载)命令行说明中格式 尖括号 中括号的含义
    Linux重启网卡服务Failed to start LSB: Bring up/down networking.
  • 原文地址:https://www.cnblogs.com/flying_bat/p/1044737.html
Copyright © 2011-2022 走看看