一、简介:
TCP_NODELAY关闭Nagle算法,控制的是数据的发送。Nagle 算法规定,如果包大于MSS(Max Segment Size)或含有FIN则立即发送,否则放入缓冲区,等已经发送的包被确认后后再发送。即网络上只能有一个未确认的小包。可以降低网络小包数量,减少了ip头部在网络上的比重,提升网络性能。
TCP_CORK:设置后不会发送任何小包(小于mss)除非超时200ms
TCP_QUICKACK (since Linux 2.4.4) 设置后会立刻发送确认ACK,而不是延迟发送ack。若未开启,则Delay ack延迟确认,使得协议有机会合并ack,提高网络利用率,默认40ms超时确认,系统值可配置。
二、测试:
2、server端开启QUICKACK,client端开启NODELAY(立刻发送):server端收到一个数据后立刻发送确认给client

3、server端关闭QUICKACK,client端开启NODELAY(立刻发送):client不等确认连续发送10个字符,server端在10ms后发送ack。疑问:为什么是10ms后发送ack”

4、server端开启QUICKACK,client端关闭NODELAY(也就是会延迟发送):server收到数据后立刻发送确认给client,client将余下9个字符合并发送。


5、server端关闭QUICKACK,client端开启TCP_CORK:client端发送10个字符,远小于MSS,故等200ms超时后发送

三、总结:
延迟与带宽利用率不可兼得。若需要降低延迟,则应开启QUICKACK、NODELAY;否则两者都关闭,提高带宽利用率。
四、附demo
server代码:
#include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <netdb.h> #include <errno.h> #include <syslog.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <netinet/tcp.h> #include <signal.h> #include <sys/wait.h> #define BUFLEN 1024 int main(int argc, char argv) { int listenfd, connfd; socklen_t clilen; struct sockaddr_in cliaddr, servaddr; listenfd = socket(AF_INET, SOCK_STREAM, 0); memset(&cliaddr, 0, sizeof(cliaddr)); memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(9000); bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)); listen(listenfd, 128); printf("listen port 9000...\n"); clilen = sizeof(cliaddr); connfd = accept(listenfd, (struct sockaddr*)&cliaddr, &clilen); if(connfd <= 0) { perror("accept error\n"); exit(1); } int quick = 1, size = 1; int rc = setsockopt(connfd, IPPROTO_TCP, TCP_QUICKACK, &quick, sizeof(int)); sleep(10); close(connfd); return 0; }
讯享网
client代码:
讯享网#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <errno.h> #include <syslog.h> #include <netinet/tcp.h> #include <sys/socket.h> #define BUFLEN 1024 int main(int argc, char argv) { int sockfd; struct sockaddr_in servaddr; if(argc !=2) { printf("usage: a.out server_addr\n"); exit(1); } sockfd = socket(AF_INET, SOCK_STREAM, 0); memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(9000); if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) { printf("invalid addr: %s\n", argv[1]); return 1; } if(connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) != 0) { printf("failed to connect to server %s, errno:%d\n", argv[1], errno); return 1; } int rc = 0; int nodelay = 1; rc = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(int)); int cork = 1; rc = setsockopt(sockfd, IPPROTO_TCP, TCP_CORK, &cork, sizeof(int)); printf("nodelay test connected, nodelay set \n"); char sendline[2] = {0}; sendline[0] = 'a'; int n = 0; for(int i = 0;i<10;i++) n+=write(sockfd, sendline, strlen(sendline)); printf("%d bytes are sent\n", n); if(read(sockfd, sendline, 2) <=0) { printf("server terminated \n"); exit(1); } return 0; }

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/36255.html