socket的O_NONBLOCK以及TCP_NODELAY

1. no-blocking

将socket设置为no-blocking意味着socket收发数据都是非阻塞的,相比于阻塞方式,需要特殊处理这个错误码:EWOULDBLOCK or EAGAIN(这两个错误码是一样的,都是35),进行重试或者重新调度。

将socket设置非阻塞有多种方法,下面会一一汇总。

1.1 fcntl设置O_NONBLOCK

POSIX的fcntl用的比较广泛,兼容性也比较好,优先推荐使用fcntl来设置,缺点是需要两次系统调用:get、set:

    /* Change the socket into non-blocking state F_SETFL is a command saying set flag and flag is 0_NONBLOCK */                                          
    const int flags = fcntl(fd, F_GETFL, 0);
    if (flags < 0) {
        return flags;
    }
    if (flags & O_NONBLOCK) {
        return 0;
    }
    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}

1.2 使用socket自带的函数

该方法优点是简单,缺点是兼容性不太好,要求Linux内核版本高于2.6.27才可以使用:

   // client side
   int socketfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);

   // server side - see man page for accept4 under linux 
   int socketfd = accept4( ... , SOCK_NONBLOCK);

1.3 ioctl设置FIONBIO

ioctl最先在UNIX系统上使用,跨平台兼容性比较差,各个系统中该系统调用的行为是不一致的,不建议使用该方式:

    int opt = 1;
    int status = ioctl(fd, FIONBIO, &opt);

2. no-delay

Nagle算法是为了减少更多的网络小数据包:如果数据小于一个限制(通常是MSS),等待接收到之前发送的数据包的ACK,在同一时间内积累用户的数据,然后发送累积的数据。
Nagle算法有助于像telnet这样的应用程序。然而,等待ACK可能会增加发送流数据时的延迟。此外,如果接收方实现了“延迟确认策略”,它将导致临时的死锁情况。在这种情况下,禁用Nagle的算法是更好的选择,可以通过设置TCP_NODELAY禁用Nagle算法。

    int opt = 1;
    int status = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));

3. ref

  • https://stackoverflow.com/questions/1543466/how-do-i-change-a-tcp-socket-to-be-non-blocking/22339017
  • http://senlinzhan.github.io/2017/02/10/Linux%E7%9A%84TCP-CORK/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值