在 TCP 套接字连接期间由对等方重置连接?

Getting connection reset by peer during TCP socket connection?

我正在制作一个小型客户端-服务器应用程序,服务器在接受后派生一个子进程,在客户端连接到它时进行多个连接,发送消息并接收响应。以下是我的代码片段: -- client.c

字符缓冲区[256];

portno=5001;    
   
   /* Create a socket point */
   sockfd = socket(AF_INET, SOCK_STREAM, 0);
   
   if (sockfd < 0) {
      perror("ERROR opening socket");
      exit(1);
   }
    
   
   bzero((char *) &serv_addr, sizeof(serv_addr));
   serv_addr.sin_family = AF_INET;
   serv_addr.sin_port = htons(portno);
   
   /* Now connect to the server */
   if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
      perror("ERROR connecting");
      exit(1);
   }
   
   /* Now ask for a message from the user, this message
      * will be read by server
   */
while(1)
{   
   printf("Please enter the message: ");
   bzero(buffer,256);
   fgets(buffer,255,stdin);
   /* Send message to the server */
   n = write(sockfd, buffer, strlen(buffer));
   
   if (n < 0) {
      perror("ERROR writing to socket");
      exit(1);
   }
   
   /* Now read server response */
   bzero(buffer,256);
   n = read(sockfd, buffer, 255);
    if(n==0)
    {
      perror("nothing to read");
    }
   
   if (n < 0) {
      perror("ERROR reading from socket");
      exit(1);
   }
    
   printf("%s\n",buffer);
}

--server.c

int main( int argc, char *argv[] ) {
   int sockfd, newsockfd, portno, clilen;
   char buffer[256];
   struct sockaddr_in serv_addr, cli_addr;
   int n, pid;
   
   /* First call to socket() function */
   sockfd = socket(AF_INET, SOCK_STREAM, 0);
   
   if (sockfd < 0) {
      perror("ERROR opening socket");
      exit(1);
   }
   
   /* Initialize socket structure */
   bzero((char *) &serv_addr, sizeof(serv_addr));
   portno = 5001;
   
   serv_addr.sin_family = AF_INET;
   serv_addr.sin_addr.s_addr = INADDR_ANY;
   serv_addr.sin_port = htons(portno);
   
   /* Now bind the host address using bind() call.*/
   if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
      perror("ERROR on binding");
      exit(1);
   }
   
   /* Now start listening for the clients, here
      * process will go in sleep mode and will wait
      * for the incoming connection
   */
   
   listen(sockfd,5);
   clilen = sizeof(cli_addr);
   
   while (1) {
      newsockfd = accept(sockfd, (struct sockaddr *)NULL,NULL);
        
      if (newsockfd < 0) {
         perror("ERROR on accept");
         exit(1);
      }
      
      /* Create child process */
      pid = fork();
        
      if (pid < 0) {
         perror("ERROR on fork");
         exit(1);
      }
      


 if (pid == 0) 
 {
     while(1)
     {
     /* This is the client process */
     close(sockfd);
     doprocessing(newsockfd);
   /**  exit(0); **/
     }
 }
      else {
         close(newsockfd);
      }
        
   } /* end of while */
}


void doprocessing (int sock) {
   int n;
   char buffer[256];
   bzero(buffer,256);
   n = read(sock,buffer,255);
       if(n==0)
    {
      perror("nothing to read");
    }
   
   if (n < 0) {
      perror("ERROR reading from socket");
      exit(1);
   }
   
   printf("Here is the message: %s\n",buffer);
   n = write(sock,"I got your message",18);
   
   if (n <= 0) {
      perror("ERROR writing to socket");
      exit(1);
   }
    
}

当我运行两者时,O/P如下:

Please enter the message: arjun
I got your message
Please enter the message: gaur
ERROR reading from socket: Connection reset by peer

请help.how解决此问题

您的客户这样做:

  • 连接到服务器
  • 向服务器发送一些数据
  • 从服务器接收一些数据
  • 向服务器发送一些数据
  • 从服务器接收一些数据
  • ...

但是您的服务器这样做(可能一次有多个连接):

  • 等待连接
  • 从客户那里收到一些东西
  • 给客户发一些东西
  • 关闭连接(通过退出唯一打开连接的进程)

因此,当客户端要发送更多数据时,服务器关闭了连接,客户端收到错误,因为服务器关闭了连接。

您需要让服务器在循环中不断接收和发送数据(这样它可以在同一个连接上发生多次),或者让客户端在每次想要发送东西时建立一个新连接。

发生的情况是:

  1. 服务器开始侦听。
  2. 客户端连接到侦听服务器。
  3. 为客户端服务的进程的服务器分支。
  4. 客户端发送数据。
  5. 截至 3 的服务进程从客户端接收日期并打印它。
  6. 从 3 开始的服务进程向客户端发送响应。
  7. 从 3 开始的服务进程。exists/ends 并由此关闭其接受的套接字(客户端的对等方)。
  8. 客户端收到响应并打印。
  9. 从 3 开始,客户端尝试向服务进程发送更多数据..
  10. 从 3..
  11. 开始,客户端尝试从服务进程中读取更多数据
  12. 第 10 步失败,因为第 3 步的服务进程已经结束(第 7 步)

分叉的子进程正在退出但未关闭 newsockfd。在某些导致连接重置而不是有序关闭的平台上。

您还需要检查 recv() 的结果是否为零并正确处理它,即不作为错误,您还需要正确使用正值 return,例如而不是

printf("%s\n",buffer);

应该是

printf("%.*s\n",n,buffer);