C语言socket清空缓存,C语言socket send()数据缓存问题

本文探讨了TCP Nagle算法如何导致数据打包发送,以及TCP_NODELAY选项如何影响数据传输。通过示例代码展示了send()调用频率对数据是否打包的影响,并提出在send()速度过快时,可能仍需要使用usleep()来避免数据缓存。同时,指出了理解和调整这些参数对于网络编程的重要性。
摘要由CSDN通过智能技术生成

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

#include

#include

#include

#include

#include

#include

#include

#include

#include

//#include

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

#include

#include

#include

#include

#include

#include

#include

#include

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_

### 回答1: usart_senddata函数是用于向串口设备发送数据的函数。其一般用法如下: ``` usart_senddata(USARTx, data); ``` 其中,USARTx表示要使用的串口设备(如USART1、USART2等),data表示要发送的数据。 需要注意的是,在使用该函数之前,需要先配置串口设备的参数(如波特率、数据位、停止位等)。 ### 回答2: USART是串行通信协议,在嵌入式系统中常常使用。USART_SendData()是一个函数,用来向USART发送数据,下面详细介绍该函数的用法。 USART_SendData()函数是针对STM32 series中的USART准备的,所以在使用前应当先初始化USART并开启相应的中断。该函数的原型如下所示: void USART_SendData(USART_TypeDef *USARTx, uint16_t Data); 函数需要传入两个参数,第一个参数是USART1、USART2等变量表示当前正在操作USART序列的编号;第二个参数表示需要发送的数据,需要转换为16位的uint16_t类型。 函数的作用是将Data传送到暂存器中,然后由硬件自动发送,所以函数本身并不阻塞。当Data的值被成功传送到数据寄存器后,USART_SR寄存器上的TXE标志位将会被置为1。在中断处理函数中,可以通过检查TXE位及上位机的标志位,判断是否需要继续发送下一个字节。 例如,要向USART1发送数据“0x55”,可以按如下方式调用该函数: uint16_t data = 0x55; USART_SendData(USART1, data); 注意,该函数发送的数据是16位,不论实际数据长度为几位,都需要将其强制转换为16位数据格式。此外,如果要发送一个字符串,则需要将该字符串逐个字节地转换为16位,然后循环调用该函数,如下所示: char* str = "Hello World!"; for(int i=0; i<strlen(str); i++) { uint16_t data = str[i]; USART_SendData(USART1, data); } 总之,USART_SendData()函数是USART通信协议中非常重要的一部分,理解其用法并合理使用可以大大提高嵌入式系统的通信效率。 ### 回答3: USART_SendData函数是STM32系列单片机中常用的一个函数,在通信编程中使用频率很高。该函数用于向USART数据寄存器中写入一个字节数据,该数据将被传输到外设或通过串口传输。 该函数在使用前需要确保USART已经被初始化,包括配置USART的波特率、数据位、停止位和奇偶校验位等参数。USART通信必须在初始化后才能进行,否则数据传输将无法顺利进行。 USART_SendData函数的原型如下: void USART_SendData(USART_TypeDef* USARTx, uint16_t Data) 该函数的参数解释如下: USARTx:USART串口设备的名称,例如USART1,USART2等; Data:要发送到串口的数据数据类型为Uint16_t; 使用该函数时,需要按照以下步骤进行: 1.先通过函数USART_Init()初始化USART串口; 2.编写需要发送的数据; 3.调用USART_SendData()函数将数据发送到USART串口; 4.等待发送完成,检查USART_SR寄存器中的TXE位是否被置位; 5.如果TXE没有置位,则等待,直到TXE被置位,继续将数据发送到USART寄存器中。 以上是USART_SendData函数的使用方法,使用该函数可以实现STM32与其他设备之间的通信。不过需要编写相应的程序来处理串口数据的传输和接收,以保证正常的数据通信。同时,还需要注意USART_SendData函数的数据类型是Uint16_t,也就是发送的数据必须是16位,超过16位的数据需要拆分成两个数据分开发送。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值