標籤:禁用 inux 調用 cpp 緩衝 listen str bytes set
send()函數預設情況下會使用Nagle演算法。Nagle演算法通過將未確認的資料存入緩衝區直到積攢到一定數量一起發送的方法。來降低主機發送零碎小資料包的數目。所以假設send()函數發送資料過快的話,該演算法會將一些資料打包後統一發出去。假設不了接這樣的情況,接收端採會遇到看似非常奇怪的問題,比方成功recv()的次數與成功send()的次數不相等。在這中情況下,接收端能夠通過recv()的傳回值是否為0來推斷髮送端是否發送完成。
通過setsockopt()的TCP_NODELAY選項來禁用Nagle演算法。但經實驗這樣的方法似乎不總是有效,只是對於同樣數量的send(),設定了TCP_NODELAY選項後recv()成功的次數要比設定之前多出幾倍。這是不是說明設定了TCP_NODELAY後,系統會進最大的努力不去緩衝。可是假設send的實在太快的話,還是會緩衝的。
因此。假設你不希望send()的資料被本機快取到一定數量之後再發送,而是send()多少次就發送多少次。穩妥的方式還是每次send之後調用一下usleep()函數,給系統一個反應的時間。
以下的範例示範了send()調用的快慢對資料是否打包的影響,凝視掉server裡的usleep(1000),會導致資料打包發送。
TCP_NODELAY是唯一使用IPPROTO_TCP層的選項,宏TCP_NODELAY的標頭檔是linux/tcp.h或者netinet/tcp.h。
由於不知到send()資料緩衝的問題,我調試一天的程式。我的五一勞動節啊!!
server.c:
#include<stdlib.h>#include<stdio.h>#include<string.h>#include<sys/types.h>#include<sys/socket.h>#include<sys/wait.h>#include<netinet/in.h>#include<netdb.h>#include<arpa/inet.h>#include<netinet/tcp.h>//#include<linux/tcp.h>int main(){int socksv, sockcl;struct sockaddr_in server_addr;struct sockaddr_in client_addr;int sin_size;if((socksv = socket(AF_INET, SOCK_STREAM, 0)) == -1){printf("sever socket fail\n");return -1;}memset(&server_addr, 0, sizeof(struct sockaddr_in));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(6001);server_addr.sin_addr.s_addr = INADDR_ANY;int r = 1;setsockopt(socksv, SOL_SOCKET, SO_REUSEADDR, &r, sizeof(int));int t = 1;if(-1 == setsockopt(socksv, IPPROTO_TCP, TCP_NODELAY, &t, sizeof(int))){printf("setsockopt fail\n");return -1;}if(bind(socksv, (struct sockaddr *)&server_addr,sizeof(struct sockaddr)) == -1){printf("server bind fail\n");return -1;}if(listen(socksv, 5) == -1){printf("server listen fail\n");return -1;}while(1){sin_size = sizeof(struct sockaddr_in);if((sockcl = accept(socksv, (struct sockaddr *)&client_addr, &sin_size)) == -1){printf("server accept fail\n");continue;}int times = 1024;int allbytes = 0;int i;for(i = 0; i < times; i++){char buf[] = "#this is a message from ptypeServer";int sendbytes;if((sendbytes = send(sockcl, buf, strlen(buf), 0)) == -1){printf("server send fail\n");}usleep(1000);allbytes += sendbytes;}printf("have send %d packages to client, allbytes=%d\n", times, allbytes);close(sockcl);}}
client.c :
#include<stdlib.h>#include<stdio.h>#include<string.h>#include<sys/types.h>#include<sys/socket.h>#include<sys/wait.h>#include<netinet/in.h>#include<netdb.h>#include<arpa/inet.h>int main(){int socksv;char buf[1024 * 1024];if((socksv = socket(AF_INET, SOCK_STREAM, 0)) == -1){printf("socket fail\n");return -1;}struct sockaddr_in server_addr;memset(&server_addr, 0, sizeof(struct sockaddr_in));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(6001);server_addr.sin_addr.s_addr = inet_addr("192.168.1.100");if(connect(socksv, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){printf("connect fail\n");return -1;}int times = 0;int allbytes = 0;int numbytes = 1;while(numbytes != 0){times++;if((numbytes = recv(socksv, buf, sizeof(buf), 0)) == -1){printf("recv fail\n");return -1;}//buf[numbytes] = ‘\0‘;//printf("numbytes=%d buf=[%s]\n", numbytes, buf);allbytes += numbytes;}printf("server is closed, have recv %d packages from server, ""allbytes=%d\n", times - 1, allbytes);}
參閱:http://baike.baidu.com/link?url=-QgA0U7iv5tno-qnorYKDMNazOeOdcGk-pKIVFcOy-n6vhoITKdzlCg1VZYjqJ1DnOlpaaA54E7HrqQX6Bc_e_
C語言socket send()資料緩衝問題