9

我有一个服务器每 5 秒向客户端发送一次数据。我希望客户端阻止 read() 直到服务器发送一些数据然后打印它。我知道 read () 默认是阻塞的。我的问题是我的客户没有阻止 read()。这很奇怪,这似乎不是一个正常的问题。

我的代码在无限循环中打印“什么都没有回来”。我在一台linux机器上,用c编程。我的代码片段如下。请指教。

while(1)
{
    n = read(sockfd, recvline, MAXLINE);
    if ( n > 0) 
    {
        recvline[n] = 0;    
        if (fputs(recvline, stdout) == EOF)
            printf("fputs error");
    }
    else if(n == 0)
        printf("Nothing came back");
    else if (n < 0)
        printf("read error");
}
return; 
4

3 回答 3

12

可能有几个原因,并且在不同的地方可能有几个例外:

  1. 检查您创建的套接字:

    sockfd=socket(AF_INET,SOCK_STREAM,0);  
    if (sockfd==-1) {
        perror("Create socket");
    }
    
  2. 您还可以在使用之前显式启用阻塞模式:

    // Set the socket I/O mode: In this case FIONBIO  
    // enables or disables the blocking mode for the   
    // socket based on the numerical value of iMode.  
    // If iMode = 0, blocking is enabled;   
    // If iMode != 0, non-blocking mode is enabled.
    ioctl(sockfd, FIONBIO, &iMode);  
    

    或者你可以使用setsockopt如下:

     struct timeval t;    
     t.tv_sec = 0;
     tv_usec = 0;
     setsockopt(
          sockfd,     // Socket descriptor
          SOL_SOCKET, // To manipulate options at the sockets API level
          SO_RCVTIMEO,// Specify the receiving or sending timeouts 
          const void *(&t), // option values
          sizeof(t) 
      );   
    
  3. 检查读取函数调用(错误原因)

    n = read(sockfd, recvline, MAXLINE);
    if(n < 0){  
        perror("Read Error:");
    }  
    
  4. 还要检查服务器代码!:

    1. 愿您的服务器发送一些空白(不可打印,空,输入)章程。而你对此一无所知。错误你的服务器代码。

    2. 或者您的服务器在您的客户端可以读取之前终止

  5. 一件更有趣的事,试着去理解:

    当您write()在服务器上调用 N 时,不需要read()在另一端调用N。

于 2012-10-08T04:45:45.583 回答
4

Greg Hewgill 已经写过评论:EOF(即明确停止写入,无论是 viaclose()还是 via shutdown())将通过recv()return 0 与接收方通信。所以如果你得到 0,你就知道赢了'不是任何数据,您可以终止读取循环。

如果您启用了非阻塞并且没有数据,您将获得-1errno设置为EAGAINor EWOULDBLOCK

于 2012-10-08T05:12:35.633 回答
2

MAXLINE 的价值是多少?

如果值为 0,那么它也将返回 0。否则,正如 Grijesh Chauhan 提到的,将其明确设置为阻塞。

或者,您也可以考虑在可以指定阻塞和非阻塞的情况下使用 recv()。它有一个选项,MSG_WAITALL,它将阻塞直到所有字节到达。

n = recv(sockfd, recvline, MAXLINE, MSG_WAITALL);
于 2012-10-08T05:02:01.940 回答