TCP之非阻塞connect和accept
2016-04-06 10:41
696 查看
套接字的默认状态是阻塞的,这就意味着当发出一个不能立即完成的套接字调用时,其进程将被投入睡眠,等待响应操作完成,可能阻塞的套接字调用可分为以下四类:
(1) 输入操作,包括read,readv,recv,recvfrom,recvmsg;
(2) 输出操作,包括write,writev,send,sendto,sendmsg;
(3) 接受外来连接,即accept函数。
(4) 发起外出连接,即tcp的connect函数;
非阻塞connect:
当一个非阻塞的tcp套接字上调用connect时,connect将立即返回一个EINPROGRESS错误,不过已经发起的tcp三路握手继续进行。我们接着使用select检测这个连接或成功或失败的已建立条件。非阻塞connect有三个用途:
(1) 我们可以把三路握手叠加在其他处理上,完成一个connect要花的RTT时间,而RTT波动很大,从局域网上的几毫秒到几百毫秒甚至是广域网的几秒。这段时间内也许有我们想要执行的其他工作可执行;
(2) 我们可以使用这个技术同时建立多个连接;这个技术随着web浏览器流行起来;
(3) 既然使用select等待连接建立,我们可以给select指定一个时间限制,使得我们能够缩短connect的超时。
非阻塞connect细节:
(1) 尽管套接字是非阻塞的,如果连接到的服务器在同一个主机上,那么当我们调用connect时候,连接通常立刻建立,我们必须处理这种情形;
(2) 源自Berkeley的实现(和posix)有关select和非阻塞connect的以下两个原则:
--(a) 当连接成功建立时,描述符变为可写;
--(b) 当连接建立遇到错误时,描述符变为既可读又可写;
非阻塞accept:
在比较忙的服务器中,在建立三次握手之后,调用accept之前,可能出现客户端断开连接的情况,再这样的情况下;如,三次握手之后,客户端发送rst,然后服务器调用accept。posix指出这种情况errno设置为CONNABORTED;
注意Berkeley实现中,没有返回这个错误,而是EPROTO,同时完成三次握手的连接会从已完成队列中移除;在这种情况下,如果我们用select监听到有新的连接完成,但之后又被从完成队列中删除,此时如果调用阻塞accept就会产生阻塞;
解决办法:
(1) 使用select监听套接字是否有完成连接的时候,总是把这个监听套接字设置为非阻塞;
(2) 在后续的accept调用中忽略以下错误,EWOULDBLOCK(Berkeley实现,客户中止连接), ECONNABORTED(posix实现,客户中止连接), EPROTO(serv4实现,客户中止连接)和EINTR(如果有信号被捕获);
(1) 输入操作,包括read,readv,recv,recvfrom,recvmsg;
(2) 输出操作,包括write,writev,send,sendto,sendmsg;
(3) 接受外来连接,即accept函数。
(4) 发起外出连接,即tcp的connect函数;
非阻塞connect:
当一个非阻塞的tcp套接字上调用connect时,connect将立即返回一个EINPROGRESS错误,不过已经发起的tcp三路握手继续进行。我们接着使用select检测这个连接或成功或失败的已建立条件。非阻塞connect有三个用途:
(1) 我们可以把三路握手叠加在其他处理上,完成一个connect要花的RTT时间,而RTT波动很大,从局域网上的几毫秒到几百毫秒甚至是广域网的几秒。这段时间内也许有我们想要执行的其他工作可执行;
(2) 我们可以使用这个技术同时建立多个连接;这个技术随着web浏览器流行起来;
(3) 既然使用select等待连接建立,我们可以给select指定一个时间限制,使得我们能够缩短connect的超时。
非阻塞connect细节:
(1) 尽管套接字是非阻塞的,如果连接到的服务器在同一个主机上,那么当我们调用connect时候,连接通常立刻建立,我们必须处理这种情形;
(2) 源自Berkeley的实现(和posix)有关select和非阻塞connect的以下两个原则:
--(a) 当连接成功建立时,描述符变为可写;
--(b) 当连接建立遇到错误时,描述符变为既可读又可写;
非阻塞accept:
在比较忙的服务器中,在建立三次握手之后,调用accept之前,可能出现客户端断开连接的情况,再这样的情况下;如,三次握手之后,客户端发送rst,然后服务器调用accept。posix指出这种情况errno设置为CONNABORTED;
注意Berkeley实现中,没有返回这个错误,而是EPROTO,同时完成三次握手的连接会从已完成队列中移除;在这种情况下,如果我们用select监听到有新的连接完成,但之后又被从完成队列中删除,此时如果调用阻塞accept就会产生阻塞;
解决办法:
(1) 使用select监听套接字是否有完成连接的时候,总是把这个监听套接字设置为非阻塞;
(2) 在后续的accept调用中忽略以下错误,EWOULDBLOCK(Berkeley实现,客户中止连接), ECONNABORTED(posix实现,客户中止连接), EPROTO(serv4实现,客户中止连接)和EINTR(如果有信号被捕获);
相关文章推荐
- K60 Lwip TCP Server实现
- TCP
- 用Java发起HTTP请求与获取状态码(含状态码列表)
- Linux C实现简单的网络聊天室
- python 获取网络时间及修改本地时间
- 网络工具wireshark和tcpdump以及netstat命令的使用
- 搭建SSL,让Apache支持Https
- HTTP Status 404 - No result defined for action com.csdhsm.struts.action.LoginAction and result error
- 写给后端程序员的HTTP缓存原理介绍
- 深入理解HTTP Session
- GetAPictureFromInternet网络编程
- SVN基于http协议
- 计算机网络知识点(一)
- http://www.blogjava.net/soken/articles/371548.html
- Android OkHttp完全解析
- Linux C高级编程——网络编程之API(5)
- 告别砸钱深挖潜力 动漫、音频、游戏重构IP新玩法
- HttpUtils工具类
- 【bzoj 1070】【codevs 2436】[SCOI2007]修车(费用流)
- HTTP请求头参数