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()数据缓存问题的更多相关文章

  1. 云计算之路-阿里云上:原来“黑色0.1秒”发生在socket读取数据时

    在昨天的博文(云计算之路-阿里云上:读取缓存时的“黑色0.1秒”)中我们犯了一个很低级的错误——把13ms算成了130ms(感谢陈硕发现这个错误!),从而对问题的原因作出了错误的推断,望大家谅解! 从 ...

  2. 文件缓存tmpfs + 数据缓存SSDB(一)

    一.文件缓存tmpfs 1.特性 1) 基于内存的文件系统,RAW+SWAP,虚拟内存 2) tmpfs使用虚拟内存,/dev/shm/使用共享内存 3) 访问速度快,可以动态调整大小 4) 没有持久 ...

  3. jQuery 2.0.3 源码分析 数据缓存

    历史背景: jQuery从1.2.3版本引入数据缓存系统,主要的原因就是早期的事件系统 Dean Edwards 的 ddEvent.js代码 带来的问题: 没有一个系统的缓存机制,它把事件的回调都放 ...

  4. Memcached 数据缓存系统

    Memcached 数据缓存系统 常用命令及使用:http://www.cnblogs.com/wayne173/p/5652034.html Memcached是一个自由开源的,高性能,分布式内存对 ...

  5. memcached基于socket访问memcache缓存服务器

    memcached基于socket访问memcache缓存服务器 操作memcache常用三种方法: .memcache基于php_memcache.dll扩展(php扩展) .memcached基于 ...

  6. 第十七课:js数据缓存系统的原理

    这一章主要讲的是jQuery的缓存系统的历史发展,以及他自己的框架的缓存系统的实现.都是源码解析. 我就挑几个重点讲下: (1)jQuery的缓存机制的原理 jQuery的缓存机制实现的原理是在元素中 ...

  7. C语言socket编程

    建议先去看一下思路 真的写的很不错呦~ 思路参考博客:https://www.cnblogs.com/renfanzi/p/5713054.html linux c语言socket编程代码(单一服务端 ...

  8. C# Socket 接受数据不全的处理

    由于Socket 一次传输数据有限,因此需要多次接受数据传输. 解决办法一:     int numberOfBytesRead = 0;     int totalNumberOfBytes = 0 ...

  9. 基于IBM Bluemix的数据缓存应用实例

    林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:IBM® Data Cache for Bluemix 是快速缓存服务.支持 Web 和 ...

随机推荐

  1. input加border-raduis之后再加border有阴影

    在border之前加入: background:no-repeat 0 0 scroll #fff;border:none;outline:medium;即可解决

  2. BZOJ 3282 Tree ——Link-Cut Tree

    [题目分析] 明显的LCT维护连通性的题目. access的操作是比较巧妙的,可以把结点到根变成偏爱路径,而且保证了该点是链上深度最深的点. 而且需边的思想也很巧妙,保证了复杂度. 但是只能用于修改路 ...

  3. 刷题总结——电影(ssoi)

    题目: 题目背景 SOURCE:NOIP2014-SXYZ T2 题目描述 小美去看电影,发现这个电影票很神奇,有一个编号 (x,y) 表示为第 x 排第 y 位. 小美是个聪明的女孩子,她有自己的一 ...

  4. 【2018.12.10】NOI模拟赛3

    题目 WZJ题解 大概就是全场就我写不过 $FFT$ 系列吧……自闭 T1 奶一口,下次再写不出这种 $NTT$ 裸题题目我就艹了自己 -_-||| 而且这跟我口胡的自创模拟题 $set1$ 的 $T ...

  5. angular中ng-repeat去重

    [html] view plain copy print?在CODE上查看代码片派生到我的代码片 <div ng-app="myApp" ng-controller=&quo ...

  6. centos7如何查看ip信息(centos 6.5以前都可以用ifconfig 但是centos 7里面没有了,centos 7用什么查看?)

    展开全部 centos7如何查看ip信息可以这样解决: 1.首先要先查看一下虚拟机的ip地址,因为ipconfig不是centos7,因此要使用 ip addr来查看. 2.查看之后你就会发现ens3 ...

  7. Count Numbers

    Count Numbers 时间限制: 8 Sec  内存限制: 128 MB 题目描述 Now Alice wants to sum up all integers whose digit sum ...

  8. AC日记——租用游艇 洛谷 P1359

    题目描述 长江游艇俱乐部在长江上设置了n 个游艇出租站1,2,…,n.游客可在这些游艇出租站租用游艇,并在下游的任何一个游艇出租站归还游艇.游艇出租站i 到游艇出租站j 之间的租金为r(i,j),1& ...

  9. Neo4j 第七篇:模式(Pattern)

    模式和模式匹配是Cypher的核心,使用模式来描述所需数据的形状,该模式使用属性图的结构来描述,通常使用小括号()表示节点,-->表示关系,-[]->表示关系和关系的类型,箭头表示关系的方 ...

  10. 四则运算表达式树 C++模板 支持括号和未知数

    首先允许我吐槽CSDN的MARKDOWN,简直难用的不行. 程序的原理是将表达式分治转换为二叉树,再在二叉树上递归计算结果.如同以下表达式:x+5*y-(6/(1-5.5))可以表达为以下二叉树(抱歉 ...