C语言socket send()数据缓存问题
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);
}
C语言socket send()数据缓存问题的更多相关文章
- 云计算之路-阿里云上:原来“黑色0.1秒”发生在socket读取数据时
在昨天的博文(云计算之路-阿里云上:读取缓存时的“黑色0.1秒”)中我们犯了一个很低级的错误——把13ms算成了130ms(感谢陈硕发现这个错误!),从而对问题的原因作出了错误的推断,望大家谅解! 从 ...
- 文件缓存tmpfs + 数据缓存SSDB(一)
一.文件缓存tmpfs 1.特性 1) 基于内存的文件系统,RAW+SWAP,虚拟内存 2) tmpfs使用虚拟内存,/dev/shm/使用共享内存 3) 访问速度快,可以动态调整大小 4) 没有持久 ...
- jQuery 2.0.3 源码分析 数据缓存
历史背景: jQuery从1.2.3版本引入数据缓存系统,主要的原因就是早期的事件系统 Dean Edwards 的 ddEvent.js代码 带来的问题: 没有一个系统的缓存机制,它把事件的回调都放 ...
- Memcached 数据缓存系统
Memcached 数据缓存系统 常用命令及使用:http://www.cnblogs.com/wayne173/p/5652034.html Memcached是一个自由开源的,高性能,分布式内存对 ...
- memcached基于socket访问memcache缓存服务器
memcached基于socket访问memcache缓存服务器 操作memcache常用三种方法: .memcache基于php_memcache.dll扩展(php扩展) .memcached基于 ...
- 第十七课:js数据缓存系统的原理
这一章主要讲的是jQuery的缓存系统的历史发展,以及他自己的框架的缓存系统的实现.都是源码解析. 我就挑几个重点讲下: (1)jQuery的缓存机制的原理 jQuery的缓存机制实现的原理是在元素中 ...
- C语言socket编程
建议先去看一下思路 真的写的很不错呦~ 思路参考博客:https://www.cnblogs.com/renfanzi/p/5713054.html linux c语言socket编程代码(单一服务端 ...
- C# Socket 接受数据不全的处理
由于Socket 一次传输数据有限,因此需要多次接受数据传输. 解决办法一: int numberOfBytesRead = 0; int totalNumberOfBytes = 0 ...
- 基于IBM Bluemix的数据缓存应用实例
林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:IBM® Data Cache for Bluemix 是快速缓存服务.支持 Web 和 ...
随机推荐
- x86保护模式-六 控制转移
控制转移可以分为两大类 :同一任务内的控制转移 和 任务间的控制转移(任务切换) 同一个任务内的控制转移可以分为段内转移 .特权级不变的段间转移和特权级改变的段间转移 段内转移与实模式相同 ...
- 九度oj 题目1172:哈夫曼树
题目描述: 哈夫曼树,第一行输入一个数n,表示叶结点的个数.需要用这些叶结点生成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即weight,题目需要输出所有结点的值与权值的乘积之和. 输入: 输入有 ...
- RR隔离级别下通过next-key locks 避免幻影读
---恢复内容开始--- mysql innodb目前使用范围最广的两种隔离级别为RC和RR,RR修复了RC中所存在的不可重复读 READ COMMITED 不可重复读 在同一事务中两次查看的结果集不 ...
- shell的while循环
while循环用于不断执行一系列命令,也用于从输入文件中读取数据:命令通常为测试条件.其格式为: while command do Statement(s) to be executed if ...
- iOS开发工具篇-AppStore统计工具
苹果官方的iTunes Connect提供的销售数据统计功能比较弱,例如只能保存最近30天的详细销售数据,界面丑陋, 无法查看App的排名历史变化情况等. 早有一些公司提供了专门的解决方案或工具.这些 ...
- BZOJ 3782 上学路线 ——动态规划 Lucas定理 中国剩余定理
我们枚举第一个经过的坏点,然后DP即可. 状态转移方程不是难点,难点在于组合数的处理. 将狼踩尽的博客中有很详细的证明过程,但是我只记住了结论 $n=a_1 * p^k+a_2*p^k-1...$ $ ...
- [BZOJ1594] [Usaco2008 Jan]猜数游戏(二分 + 并查集)
传送门 题中重要信息,每堆草的数量都不一样. 可以思考一下,什么情况下才会出现矛盾. 1.如果两个区间的最小值一样,但是这两个区间没有交集,那么就出现矛盾. 2.如果两个区间的最小值一样,并且这两个区 ...
- 常州模拟赛d3t2 灰狼呼唤着同胞
题目背景 我的母亲柯蒂丽亚,是一个舞者.身披罗纱,一身异国装扮的她,来自灰狼的村子. 曾经在灰狼村子担任女侍的她,被认定在某晚犯下可怕的罪行之后,被赶出了村子. 一切的元凶,都要回到母亲犯下重罪的那一 ...
- C#.net的常用函数列表
原文发布时间为:2008-08-03 -- 来源于本人的百度文章 [由搬家工具导入] 1、DateTime 数字型 System.DateTime currentTime=new System.Dat ...
- golang文件下载断点续传(下载客户端)
客户端: //const ( // UA = "Golang Downloader from Kejibo.com" //) func DownloadController(ctx ...