阻塞:通常的I/O操做能够在新建的流中运用.在服务器回应前它等待客户端发送一个空白的行.当会话结束时,服务器关闭流和客户端socket.若是在队列中没有请示将会出现什么状况呢?那个方法将会等待一个的到来.这个行为叫阻塞.accept()方法将会阻塞服务器线程直到一个呼叫到来.当5个链接处理完闭以后,服务器退出.任何的在队列中的呼叫将会被取消.
非阻塞:非阻塞套接字是指执行此套接字的网络调用时,不论是否执行成功,都当即返回。好比调用recv()函数读取网络缓冲区中数据,不论是否读到数据都当即返回,而不会一直挂在此函数调用上。在实际Windows网络通讯软件开发中,异步非阻塞套接字是用的最多的。日常所说的C/S(客户端/服务器)结构的软件就是异步非阻塞模式的。
具体机制就是上面所说的,简明扼要的来讲能够打个比方:
你有数个同窗来访 <---> 有若干数据须要收取
你时不时的去门口看看,没有看到你同窗的话就回客厅等待,看到同窗就接到客厅来 <---> 非阻塞模式,不管收到数据与否都返回
你一直在门口等着你同窗,接到后才回客厅 <---> 阻塞模式,接收到数据后才返回
使用阻塞怎么了?会带来什么后果?在什么状况之下?对性能有影响么?
套接字有两种模式,阻塞模式与非阻塞模式。默认建立的为阻塞模式.
在blocking model 下:
套接字在IO时阻塞应用程序,就是说控制权不会返回给应用程序,也就是说程序执行到此代码时会卡住。分两种状况,1.send函数时,只有把要发送的数据下传至TCP层,send这句代码才继续向下执行,此时可确认本身的数据已经在网络上传输了2.recv时,只有收到必定数据给应用程序缓冲区时,recv这行代码才会向下执行。若是不想这样作,可使用多线程,或者选用其余网络IO模型。通常在作服务器程序时,不会使用阻塞套接字,性能低,数据吞吐率也不高。优势是此种模型编写难度较低,能够用来作入门的学习之用。
非阻塞套接字,IO会立刻返回.但在send时,若是SOCKET缓冲区已满,会返回错误,使用WSAGetLastError会获得错误码为WSAEWOULDBLOCK,意思是说在一个非阻塞的套接字上,请求没有完成。recv时若是SOCKET缓冲区没有能够读的数据,也会返回WSAEWOULDBLOCK.
Socket 的模式大概分为这么几种:
一、阻塞式的,Socket操做都须要将线程挂起,等待内核完成后才能返回。
如: 调用connect=>进入内核=>Syn包=〉服务器返回SYN ACK 包=〉connect返回。
=〉ACK包发往服务器。
但通常来讲,阻塞和非阻塞对于recv来讲意义更大。
当在阻塞式的Socket上调用recv时,若是这时网络栈上没有数据给你接收,那么这时线程将
会挂起,直到有报文给你接收才返回。
这样就形成你的应用程序在企图接收数据时候,而网络栈上没有数据的时候就会被锁住。
有什么办法解决这个问题呢? 咱们来介绍IO
二、 IO复用, 就是在企图读写数据的时候先询问下是否可读写,若是不能,能够去干别的事情,不会形成死锁。
可是假如咱们有大量的链接须要去频繁的查询可读写状态,每次查询都会和内核交互。这样会形成
效率低下。再介绍一种
三、 重叠IO. 就是一次查询多个Socket的状态。不用去来来回回的遍历。
另外,
在windows socket api 中还有一种消息机制,就是把Socket状态通知到窗口。而后用消息去处理。
对于重叠IO, 在windows上还有完成端口模型,他和重叠端口相比,不但能捕捉到IO事件, 并且内核已经替你完成了Socket IO, 好比read事件, 在内核通知你的时候,他已经帮你读好数据了,并放在你指定的缓存中(这里是指在用户态下,事先为每一个Socket分配的内存)。
为何有这么多socket模式呢? 哪一个更好呢?
为何有,我不知道,多是出于需求吧,
说说哪一个更好?
孤立的来讲,其实没有哪一个更好? 只有哪一个更适合你的应用应用环境。
如: 阻塞式的比较简单,方便,稳定。适合比较简单的客户端程序。
IO复用我认为它适合SocketIO操做比较少的状况。
重叠IO就适合高性能的服务器的开发,另外完成端口是windows上比较公认的高性能服务器的网络开发模型。固然, windows 的IOCP也有个坏处,就是须要大量的内存,应为前面说了他须要事先指定缓存。不太高性能的 服务器,通常都不用windows平台。
windows的消息模型就比较适合有UI的应用程序。
固然, 有些模型的选择上可能还有我的爱好的因素,
如, 我可能不喜欢用消息模型,
我不喜欢被动的被通知, 而喜欢主动的去查询。windows