tcp学习(一)非阻塞connect和accept

1 非阻塞connect

1.1 阻塞模式与非阻塞

调用connect会发起三次连接。

阻塞模式下,connect的返回结果:

  • 发出syn分节后,对方没有收到对端的syn分节,这时会返回ETIMEOUT。超时时间大概在75秒左右。
  • 发出syn分节后,对方没有在监听指定的端口,便会回复RST。这时返回ECONNREFUSED。
  • 发出syn分节后,引发路由器一个ICMP目的不可达的错误。多次尝试后仍无法成功发送,这时会返回EHOSTUNREACH或者ENETUNREACH。

非阻塞模式下,调用connect后会立刻返回EINPROGRESS,同时三次握手还在进行。

1.2 非阻塞模式的实现

int socfd = socket();
//set non-blocking
int ret = connect(sockfd, ...);
if(ret < 0)
{
    return -1;
}
if(errno == EINPRPGRESS)
{
    fd_set rdset, wrset;
    FD_SET(sockfd, rdset);
    FD_SET(sockfd, wrset);
    ret = select(sockfd+1, &rdset, &wrset, NULL, timeout);
    if(FD_ISSET(sockfd, &wrset))
    {
        if(FD_ISSET(sockfd, rdset))
        {
            //清楚sock error
        }
        //成功连接
        return sockfd.
    }
}

1.3 非阻塞connect的意义

非阻塞connect的意义在于提高并发度。阻塞connect下,完成一个三次握手需要耗费一个RTT时间。RTT时间波动很大。从局域网内的几时毫秒到广域网的几十秒。阻塞模式下,进程被connect阻塞住,什么都干不了。非阻塞下,我们可以让select或者epoll来监听listenfd,直到完成三次连接再继续进行数据的手法。

2 非阻塞accept

2.1 非阻塞accept的实现

int sockfd = socket();
//set non-blocking
bind()
fd_set rdset;
FD_SET(sockfd, &rdset);
while(1)
{
    int ret = select(sockfd+1, &rdset, NULL, NULL, timeout);
    if(ret < 0)
    {
        // err log
    }
    if(errno == EPROTO || ...)
    {
        continue;
    }
    int accept(sockfd,...);
}

2.2 注意点

完成三次连接后,accept之前,select为可读,这个时候如果对端关闭连接,accept这个关闭的sockfd会阻塞。

所以select返回后,accept前,总是忽略EWOULDBLOCK和ECONNABORTED、EPROTO、EINTR。

2.3 非阻塞accept的意义

非阻塞accept的意义同样在于提高并发度。



链接:https://www.jianshu.com/p/4c01c0620143
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值