【问题标题】:C socket TCP server fails after client disconnects客户端断开连接后 C 套接字 TCP 服务器失败
【发布时间】:2019-05-11 19:20:54
【问题描述】:

我正在从这里http://www.linuxhowtos.org/C_C++/socket.htm 修改服务器代码。我想在客户端断开连接时重置服务器,以便下次为客户端准备好。但是当我关闭客户端时,服务器关闭并且服务器日志中没有任何内容。由于我一次只想处理一个客户,所以我不需要分叉,对吗?否则,服务器可以正常工作并响应我用 C# 编写的客户端发送的消息。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

FILE *fp;

double square(double x)
{
     return x*x;
}

void error(const char *msg)
{
     fprintf(fp, "%s", msg);
     fprintf(fp, "%s", "\n");
}

int main(int argc, char *argv[])
{
     fp = fopen("serverlog.txt", "a");

     int sockfd;
     int newsockfd;
     int portno = 43635;
     int clientIsConnected;

     socklen_t clilen;
     char buffer[256];

     struct sockaddr_in serv_addr, cli_addr;
     int n;

while (1)
{
     sockfd = socket(AF_INET, SOCK_STREAM, 0);

     if (sockfd < 0)
     { 
          error("ERROR opening socket");
          close(sockfd);
          return 0;
     }

     bzero((char *) &serv_addr, sizeof(serv_addr));

     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno);

     if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 
     {
          error("ERROR on binding");
          close(sockfd);
          return 0;
     }

     if (listen(sockfd,5) < 0)
     {
          error("ERROR on listen");
          close(sockfd);
          return 0;
     }

     clilen = sizeof(cli_addr);
     newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);

     if (newsockfd < 0) 
     {
          error("ERROR on accept");
          close(newsockfd);
          close(sockfd);
          return 0;
     }

     clientIsConnected = 1;

     while (clientIsConnected)
     {
          bzero(buffer, 256);
          n = read(newsockfd, buffer, 255);

          if (n < 0)
          {
               error("ERROR reading from socket");
               clientIsConnected = 0;
               break;
          }

          double x = atof(buffer);
          double squared = square(x); 
          char response[256];
          sprintf(response, "%f", squared);

          n = write(newsockfd, response, strlen(response));

          if (n < 0)
          { 
               error("ERROR writing to socket");
               clientIsConnected = 0;
               break;
          }
     }
}

     close(sockfd);
     return 0; 
}

【问题讨论】:

  • 如果这不是一个玩具项目,我建议使用现有的库来处理网络层。您会发现这抽象出了很多与网络相关的问题,例如部分write 调用、意外断开连接等。

标签: c linux sockets tcp


【解决方案1】:

您的服务器可能因为收到 SIGPIPE 而停止。你可以使用

信号(SIGPIPE,SIG_IGN);

为了让你的程序继续运行,你可以在你的应用程序代码中处理封闭的通信。

【讨论】:

  • 请注意,signal() 方法会在整个过程中禁用SIGPIPE。另一种选择是仅通过setsockopt(SO_SIGNOPIPE)MSG_NOSIGNAL on send() 为套接字禁用SIGPIPE
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-04
  • 1970-01-01
  • 2013-03-28
  • 1970-01-01
  • 2021-12-28
  • 1970-01-01
相关资源
最近更新 更多