12.23

code in pic 12-8 save as file 12.23.bug.c

run server

(cd ./site/content/chapter12/code; make && ./12.23.bug)

let’s figure out when server will fail, see code 12.23.client.c

/*
 * 12.23.client.c - An echo client
 */
#include "csapp.h"

int main(int argc, char **argv)
{
  int clientfd;
  char *host, *port;
  char *buf = "something to send\n";
  rio_t rio;

  host = "127.0.0.1";
  port = "5000";

  clientfd = Open_clientfd(host, port);

  Rio_readinitb(&rio, clientfd);
  Rio_writen(clientfd, buf, strlen(buf));
  /*Close(clientfd);*/
  exit(0);
}

line 20 Close(clientfd) are commented. when server is running, open another terminal and run ./12.23.client, server will exit with error

Rio_readlineb error: Connection reset by peer

server can’t read EOF because client doesn’t call Close

how to fix:

just output error infomation and doesn’t exit

--- 12.23.bug.c	2021-02-25 07:26:33.302592754 +0000
+++ 12.23.c	2021-02-25 07:26:33.302592754 +0000
@@ -1,7 +1,5 @@
 /*
- * 12.23.bug.c - A concurrent echo server based on select
- *
- * bug in this file
+ * 12.23.c - A concurrent echo server based on select
  */
 #include "csapp.h"
 
@@ -105,15 +103,21 @@
     /* If the descriptor is ready, echo a text line from it */
     if ((connfd > 0) && (FD_ISSET(connfd, &p->ready_set))) {
       p->nready--;
-      if ((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) {
+      if ((n = rio_readlineb(&rio, buf, MAXLINE)) > 0) {
         byte_cnt += n; //line:conc:echoservers:beginecho
         printf("Server received %d (%d total) bytes on fd %d\n",
             n, byte_cnt, connfd);
         Rio_writen(connfd, buf, n); //line:conc:echoservers:endecho
       }
-
       /* EOF detected, remove descriptor from pool */
+      else if (n == 0) {
+        Close(connfd); //line:conc:echoservers:closeconnfd
+        FD_CLR(connfd, &p->read_set); //line:conc:echoservers:beginremove
+        p->clientfd[i] = -1;          //line:conc:echoservers:endremove
+      }
+      /* n == -1, it's an error */
       else {
+        fprintf(stderr, "error in fd %d, close fd %d connection\n", connfd, connfd);
         Close(connfd); //line:conc:echoservers:closeconnfd
         FD_CLR(connfd, &p->read_set); //line:conc:echoservers:beginremove
         p->clientfd[i] = -1;          //line:conc:echoservers:endremove
comments powered by Disqus