阻塞和非阻塞socket总结

非阻塞socket设置方法:

fcntl(socket_fd, F_SETFL,  fcntl (socket_fd, F_GETFL,0) | O_NONBLOCK);

非阻塞模式下错误处理:

EAGAIN和EWOULDBLOCK(windows下)错误,这表明你在非阻塞模式下调用了阻塞操作,在该操作没有完成就返回这个错误,关于此错误一种说法是此错误表示目前无端口可用,另一种说法说的是发送缓冲区已满,遇到这两种错误不能当作错误处理,一种处理方法是采用延时处理稍后发送/接收,另一种是在类似poll/select/epoll中继续监听下次继续发送/接收,很显然第一种方法不可取,影响性能。当发送大量数据时,可以通过缓存保存数据。如果出现EINTR错误,错误描述为Interrupted system call,操作也应该继续。如果recv的返回值为0,那表明连接已经断开,我们的接收操作也应该结束。

发送数据:

阻塞与非阻塞send返回值没有区分,

<0,出错,

=0,连接关闭,

>0,发送数据大小。

非阻塞模式下返回值 <0时并且(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)的情况下认为连接是正常的, 继续发送。

阻塞模式下send会阻塞着发送数据,非阻塞模式下如果暂时无法发送数据会返回,不会阻塞着 send,因此需要循环发送。

接收数据:

阻塞与非阻塞recv返回值没有区分,

<0,出错,

=0,连接关闭,

>0,接收到数据大小,

非阻塞模式下返回 值 <0时并且(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)的情况 下认为连接是正常的,继续接收。

阻塞模式下recv会阻塞着接收数据,非阻塞模式下如果没有数据会返回,不会阻塞着读,因此需要 循环读取。

连接:

TCP socket 被设为非阻塞后调用 connect ,connect 函数如果没有马上成功,会立即返回EINPROCESS(如果被中断返回EINTR) ,但 TCP 的 3 次握手还在继续进行。之后可以用 select /epoll检查连接是否建立成功(但不能再次调用connect,这样会返回错误EADDRINUSE)。

非阻塞 connect 有3 种用途:

(1). 在3 次握手的同时做一些其他的处理。

(2). 可以同时建立多个连接。

(3). 在利用 select/epoll 等待的时候,可以给 select/epoll 设定一个时间,从而可以缩短 connect 的超时时间。

使用非阻塞 connect 需要注意的问题是:

(1). 很可能 调用 connect 时会立即建立连接(比如,客户端和服务端在同一台机子上),必须处理这种情况。

(2). Posix 定义了两条与 select/epoll 和 非阻塞 connect 相关的规定:

连接成功建立时,socket 描述字变为可写。(连接建立时,写缓冲区空闲,所以可写)

连接建立失败时,socket 描述字既可读又可写。 (由于有未决的错误,从而可读又可写)

另外对于无连接的socket类型(SOCK_DGRAM),客户端也可以调用connect进行连接,此连接实际上并不建立类似SOCK_STREAM的连接,而仅仅是在本地保存了对端的地址,这样后续的读写操作可以默认以连接的对端为操作对象。



作者:明明就_c565
链接:https://www.jianshu.com/p/286fc6f992b6
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章