2014-03-31 82 views
3

我想写一个实验性的客户端/服务器程序来证明写入失败或发送缓冲区已满时阻止。 基本上,我在发件人程序上有一个无限循环,我使用select()来检查是否可以在缓冲区上写入(我认为这意味着套接字缓冲区未满),如果我可以在缓冲区上写入比我写()一个字符。当FD_ISSET(sockfd,& writefds)为假(我无法在缓冲区写入,因为它已满)时,循环中断。 开始阅读前,接收器程序正在睡眠一分钟()。我希望发件人在这个睡眠时间内填充缓冲区,但事实上,程序永远不会结束。C - 填充TCP套接字发送缓冲区

发件人:

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; 
} 

reciever:

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; 
} 
+0

你应该添加你的代码来创建套接字,以确保它是面向连接的而不是UDP。 – trev

回答

0

你在正确的轨道上,但套接字发送缓冲区可能是48K以上。这是很多迭代。尝试一次写8k,而不只是一个字节。并增加接收器读取之前的时间。

NB没有真正的需要测试这个。它在阻塞模式下阻塞,并且在非阻塞模式下使用EAGAIN/EWOULDBLOCK失败。见男子页面。

+0

非常感谢您的回答。我编辑我的代码,在每次写入()调用时写入更多内容并等待更长时间。我已经注意到printf()发送方停止在2600000字节后以随机数字节写入数据。比等待接收者读取缓冲区的时间(我猜),然后开始无休止地写。但我从来没有得到“我无法写入套接字缓冲区”消息。 – selfm

+0

发送套接字是否处于非阻塞模式?如果不是,当发送缓冲区已满时,它会阻塞*。 – EJP

+0

发送套接字未处于非阻止模式。我认为write()会阻止,但只是片刻,然后开始写。我无法理解为什么如果(FD_ISSET(sockfd,&writefds))总是错误的。 – selfm

0

您选择的超时时间为空,因此select()将在发送缓冲区已满时阻塞。这意味着它返回时,套接字是可写的,并且永远不会到达您的代码“我无法在套接字缓冲区中写入”。

请参见手册页http://linux.die.net/man/2/select

如果你想有一个零超时,即不要select()块,你需要一个指针传递给设置为零两个字段中的timeval结构。