Mathew
Mathew

Reputation: 645

read() is not blocking in socket programming

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.

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.

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; 

Upvotes: 12

Views: 48484

Answers (3)

Grijesh Chauhan
Grijesh Chauhan

Reputation: 58251

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 setsockopt as 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.

Upvotes: 15

glglgl
glglgl

Reputation: 91017

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.

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

Upvotes: 4

Hong Zhou
Hong Zhou

Reputation: 649

What is the value of MAXLINE?

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

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.

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

Upvotes: 2

Related Questions