Nonblocking I/O

 

Nonblocking I/O  (chapter 16)



Non-blocking read/write:

 

To set a socket non-blocking:

             val = Fcntl (sockfd, F_GETFL, 0);
        Fcntl (
sockfd, F_SETFL, val | O_NONBLOCK);

 

 

To read  from the socket we use:

        if ( (n = read (sockfd, buffer, buffer_lenght)) < 0) {
                                if (errno != EWOULDBLOCK)
                                        err_sys("read error on socket");
       }
 


Non-blocking Connect:

 

    connect_nonb.c

 

     ………………

 

           flags = Fcntl(sockfd, F_GETFL, 0);

          Fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);

 

          error = 0;

          if ( (n = connect (sockfd, (struct sockaddr *) saptr, salen)) < 0)

                   if (errno != EINPROGRESS)

                             return(-1);

 

          /* Do whatever we want while the connect is taking place. */

 

          if (n == 0)

                   goto done;          /* connect completed immediately */

 

          FD_ZERO(&rset);

          FD_SET(sockfd, &rset);

          wset = rset;

          tval.tv_sec = nsec;

          tval.tv_usec = 0;

 

          if ( (n = Select(sockfd+1, &rset, &wset, NULL,

                                                 nsec ? &tval : NULL)) == 0) {

                   close(sockfd);              /* timeout */

                   errno = ETIMEDOUT;

                   return(-1);

          }

 

……………………

 

Example:     nonbDaytimeClient.c    it uses    tcpDaytimeServer.c

 

tcpDaytimeServer      <port>    <listen-backlog>   <sleep-before-accept>

nonbDaytimeClient    <ip>             <port>             <max-wait-time>

% cd  /home/cs779/stevens3rd.book/unpv13e/nonblock/example

% tcpDaytimeServer      1234     0       25          &
% nonbDaytimeClient    127.0.0.1    1234       &     ( gets the time)
% nonbDaytimeClient    127.0.0.1    1234   10   &     (timeout)
% nonbDaytimeClient    127.0.0.1    1234   50   &     (gets the time)
  


 

Non-blocking Accept:
 

We may use select to achieve non-blocking accept.

 

 

Bizarre Scenario:

 

·      Client that connect then send RST  (tcpcli03.c)

 

·      Modify select example (tcpservselect03.c)  so it may block:

 

              if (FD_ISSET(listenfd, &rset)) {       /* new client connection */
                        printf("listening socket readable\n");
                        sleep(5);  
                        clilen = sizeof(cliaddr);
                        connfd = Accept (listenfd, (SA *) &cliaddr, &clilen);

 

% cd  /home/cs779/stevens2nd.book/unpv12e/nonblock

% tcpservselect03

% tcpcli01 127.0.0.1

% tcpcli03 127.0.0.1
This will cause a problem to tcpcli01  (no more echo)

% tcpcli01 127.0.0.1
This will work fine and also makes the first tcpcli01 to work again.

 

This problem is fixed on Solaries 10.

Repeat the above using:

%  cd  /home/cs779/stevens3rd.book/unpv13e/nonblock