C - 填充 TCP 套接字发送缓冲区
Posted
技术标签:
【中文标题】C - 填充 TCP 套接字发送缓冲区【英文标题】:C - filling TCP socket send buffer 【发布时间】:2014-05-10 18:14:46 【问题描述】:我正在尝试编写一个实验性的客户端/服务器程序,以证明当发送缓冲区已满时写入是否失败或阻塞。 基本上,我在发送方程序上有一个无限循环,我使用 select() 检查是否可以在缓冲区上写入(我认为这意味着套接字缓冲区未满),如果我可以在缓冲区上写入而不是我 write() 一个字符。当 FD_ISSET(sockfd, &writefds) 为假时循环中断(我无法在缓冲区上写入,因为它已满)。 接收程序在开始 read() 之前会休眠一分钟。我希望发送者在这段睡眠时间内填满缓冲区,但实际上,程序永远不会结束。
发件人:
int main(int argc, char *argv[])
char buffer[100];
int sockfd, total = 0, bytes = 0;
fd_set writefds;
sockfd = dial(argv[1], argv[2]);
bzero(buffer, sizeof buffer);
while(1)
int ret = 0;
FD_ZERO(&writefds);
FD_SET(sockfd, &writefds);
if((ret = select(sockfd + 1, NULL, &writefds, NULL, 0)) < 0)
perror("select");
exit(errno);
if(FD_ISSET(sockfd, &writefds))
write(sockfd, "a", 1);
total++;
continue;
else
puts("I can't write in the socket buffer");
break;
printf("nb chars written: %d\n", total);
return 0;
收件人:
int foo(int sockfd)
char buffer[100];
int t, total = 0;
bzero(buffer, sizeof buffer);
printf("I have a new client\n");
sleep(60);
while((t = read(sockfd, buffer, sizeof buffer)) > 0)
total += t;
printf("%d ", total);
printf("nb chars read: %d\n", total);
if(t < 0)
perror("read");
printf("I don't have that client anymore\n");
return 0;
【问题讨论】:
您应该添加用于创建套接字的代码,以确保它是面向连接的而不是 UDP。 【参考方案1】:您的选择超时为空,因此select()
将在发送缓冲区已满时阻塞。这意味着当它返回时,套接字是可写的,你永远不会得到你的代码“我不能在套接字缓冲区中写入”。
参见手册页http://linux.die.net/man/2/select
如果您想要零超时,即不要阻塞select()
,您需要将指针传递给两个字段都设置为零的 timeval 结构。
【讨论】:
【参考方案2】:您在正确的轨道上,但套接字发送缓冲区可能是 48k 或更多。这是很多迭代。尝试一次写入 8k,而不仅仅是一个字节。并增加接收器读取前的时间。
NB 没有必要对此进行测试。它在阻塞模式下阻塞,并在非阻塞模式下以 EAGAIN/EWOULDBLOCK 失败。请参阅 man 页面。
【讨论】:
非常感谢您的回答。我已经编辑了我的代码,以便在每次 write() 调用时编写更多内容并等待更长的时间。我注意到 printf() 发送方在 2600000 字节后停止写入随机字节数。比它等待接收者读取缓冲区的时间(我猜)然后开始无休止地写入。但我从未收到“我无法在套接字缓冲区中写入”消息。 发送套接字是否处于非阻塞模式?如果不是,它将在发送缓冲区已满时阻塞。 发送套接字未处于非阻塞模式。我认为 write() 确实会阻塞,但只是片刻,然后它会永远开始写入。我无法理解为什么 if(FD_ISSET(sockfd, &writefds)) 总是错误的。 我不明白“阻止”和“永远写作”之间的区别。由于发送缓冲区已满时套接字阻塞,因此您的 select() 永远没有机会看到它。尝试非阻塞模式。以上是关于C - 填充 TCP 套接字发送缓冲区的主要内容,如果未能解决你的问题,请参考以下文章
Linux:在 TCP 套接字上发送整个消息或不发送任何消息