LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1653|回复: 7

Why Linux不用Nagle算法,而FreeBSD使用?

[复制链接]
发表于 2009-5-6 13:58:45 | 显示全部楼层 |阅读模式
用socket编了个程序,但是在Linux下面没有使用Nagle算法,而我切换到FreeBSD下面,发现BSD使用了。Nagle算法可能产生糊涂窗口综合症,但是也有相应的消除方法的。请问Linux怎么没有用呢?
发表于 2009-5-6 15:58:52 | 显示全部楼层
一般来说完整的tcp栈都会实现nagle算法,linux应该是使用的,并且需要TCP_NODELAY来显式关闭此特性。
如果你发现每个小tcp包都立即被发送,可能是因为网络轻载以及延迟很低,nagle算法里指出只有管道中有未ack的数据时才会将新数据缓存,如果每个小tcp包都及时有回应,数据传输的方式应当同没有nagle算法是一样的。
关于linux和bsd具体的实现方式我也不清除。
很久没碰网络的东西了,可能有错,供拍砖。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-5-6 16:10:56 | 显示全部楼层
UNIX® Network Programming Volume 1, Third Edition: The Sockets Networking API
daytime client and server.

Linux:
The times is:1
Mon May  4 20:00:07 2009

FreeBSD:
The times is:1
MThe times is:2
on May  4 11:51:49 2009
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-5-6 16:11:39 | 显示全部楼层
daytimetcpsrv.c

  1. #define MAXLINE 4096

  2. #include <netinet/in.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <time.h>
  7. #include <unistd.h>
  8. #include <errno.h>

  9. int main(int argc, char **argv)
  10. {
  11.         int listenfd, connfd, listenq = 1024;
  12.         struct sockaddr_in servaddr;
  13.         char buff[MAXLINE];
  14.         time_t ticks;
  15.        
  16.         if ( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  17.         {
  18.                 printf("socket error");
  19.                 exit(1);
  20.         }

  21.         bzero(&servaddr,sizeof(servaddr));
  22.         servaddr.sin_family = AF_INET;
  23.         servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  24.         servaddr.sin_port = htons(9999);

  25.         if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
  26.         {
  27.                 printf("bind error");
  28.                 exit(1);
  29.         }
  30.        
  31.         if (listen(listenfd, listenq) < 0)
  32.         {
  33.                 printf("listen error");
  34.                 exit(1);
  35.         }
  36.        
  37.         for ( ; ; )
  38.         {
  39.                 if ( (connfd = accept(listenfd, (struct sockaddr *)NULL, NULL)) < 0)
  40.                 {
  41.                         if (errno == EPROTO || errno == ECONNABORTED)
  42.                                 continue;
  43.                         else
  44.                         {
  45.                                 printf("accept error");
  46.                                 exit(1);
  47.                         }
  48.                 }

  49.                 ticks = time(NULL);
  50.                 snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
  51.                 int i;
  52.                 for (i = 0; i < strlen(buff); i++)
  53.                         write(connfd, &buff[i], 1);
  54. /*                if (write(connfd, buff, strlen(buff)) != strlen(buff))
  55.                 {
  56.                         printf("close error");
  57.                         exit(1);
  58.                 }
  59. */
  60.                 if (close(connfd) == -1)
  61.                 {
  62.                         printf("close error");
  63.                         exit(1);
  64.                 }
  65.         }
  66. }
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-5-6 16:13:08 | 显示全部楼层
daytimetcpcli.c
  1. #define MAXLINE 4096
  2. #include <netinet/in.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <arpa/inet.h>
  7. #include <unistd.h>
  8. int main(int argc, char **argv)
  9. {
  10.         int sockfd, n;
  11.         int counter = 0;
  12.         char recvline[MAXLINE + 1];
  13.         struct sockaddr_in servaddr;
  14.         if(argc != 2)
  15.         {
  16.                 printf("usage: a.out <IPaddress>");
  17.                 exit(1);
  18.         }
  19.         if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  20.         {
  21.                 printf("socket error");
  22.                 exit(1);
  23.         }
  24.         bzero(&servaddr, sizeof(servaddr));
  25.         servaddr.sin_family = AF_INET;
  26.         servaddr.sin_port = htons(9999);
  27.         if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
  28.         {
  29.                 printf("inet_pton error for %s", argv[1]);
  30.                 exit(1);       
  31.         }
  32.         if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
  33.         {
  34.                 printf("connect error");
  35.                 exit(1);
  36.         }
  37.         while( (n = read(sockfd, recvline, MAXLINE)) > 0)
  38.         {
  39.                 recvline[n] = 0;
  40.                 printf("The times is:%d\n",++counter);
  41.                 if(fputs(recvline, stdout) == EOF)
  42.                 {
  43.                         printf("fputs error");
  44.                         exit(1);
  45.                 }
  46.         }
  47.         if(n < 0)
  48.         {
  49.                 printf("read error");
  50.                 exit(1);
  51.         }
  52.         exit(0);
  53. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2009-5-6 18:31:51 | 显示全部楼层
Post by LaoLiulaoliu;1984131

Linux:
The times is:1
Mon May  4 20:00:07 2009

FreeBSD:
The times is:1
MThe times is:2
on May  4 11:51:49 2009
略了一眼程序,这不是说明linux用了这个算法么
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-5-6 19:19:55 | 显示全部楼层
TCP/IP详解上面说
  该算法要求一个 T C P连接上最多只能有一个未被确认的未完成的小分组,在该分组的确
认到达之前不能发送其他的小分组。

Nagle算法重点是第一个包用于测试网络,接下来的包才一起发送。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-4-12 23:47:48 | 显示全部楼层
$ ./client 127.0.0.1
The times is:1
MThe times is:2
on Apr 12 23:41:49 2010
$ ./client 127.0.0.1
The times is:1

今天重新在Linux上面执行,发现结果根据网络状况会不同。哈哈
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表