Linux read() 在套接字编程中不会阻塞

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12773509/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 14:32:11  来源:igfitidea点击:

read() is not blocking in socket programming

clinuxsocketsnetwork-programming

提问by Mathew

I have a server that sends data to a client every 5 seconds. I want the client to block on read() until the server sends some data and then print it. I know read () is blocking by default. My problem is that my client is not blocking on read(). This is very odd and this does not seem to be a normal issue.

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

My code prints "Nothing came back" in an infinite loop. I am on a linux machine, programming in c. My code snippet is below. Please advice.

我的代码在无限循环中打印“什么都没有回来”。我在一台 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; 

采纳答案by Grijesh Chauhan

There may be several cause and several exceptions are possible at different place:

可能有多种原因,不同地方可能出现多种异常:

  1. check socket where you create:

    sockfd=socket(AF_INET,SOCK_STREAM,0);  
    if (sockfd==-1) {
        perror("Create socket");
    }
    
  2. You and also enable blocking mode explicitly before use it:

    // 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);  
    

    or you can use setsockoptas below:

     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. Check Read function call (Reason of bug)

    n = read(sockfd, recvline, MAXLINE);
    if(n < 0){  
        perror("Read Error:");
    }  
    
  4. Also check server code!:

    1. May your server send some blank(non-printable, null, enter) charter(s). And your are unaware of this. Bug you server code too.

    2. Or your server terminated before your client can read.

  5. One more interesting thing, Try to understand:

    When you call N write()at server its not necessary there should be N read()call at other side.

  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。

回答by Hong Zhou

What is the value of MAXLINE?

MAXLINE 的价值是什么?

If the value is 0, then it will return 0 as well. Otherwise, as Grijesh Chauhan mention, set it explcitly to blocking.

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

Or, you may also consider using recv() where blocking and non-blocking can be specified. It has the option, MSG_WAITALL, where it will block until all bytes arrived.

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

n = recv(sockfd, recvline, MAXLINE, MSG_WAITALL);

回答by glglgl

What Greg Hewgill already wrote as a comment: An EOF (that is, an explicit stop of writing, be it via close()or via shutdown()) will be communicated to the receiving side by having recv()return 0. So if you get 0, you know that there won't be any data and you can terminate the reading loop.

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

If you had non-blocking enabled and there are no data, you will get -1and errnowill be set to EAGAINor EWOULDBLOCK.

如果你有非阻断启用,并且没有数据,你会得到-1errno将被设置为EAGAINEWOULDBLOCK