服务器关闭并重新启动后,客户端无法连接

Clients unable to connect after server shutdown and restart

本文关键字:客户端 连接 重新启动 服务器      更新时间:2023-10-16

我的C++网络代码(一个接收字符串并显示字符串的测试服务器)有问题。偶尔,当我关闭服务器(Ctrl-C)然后重新启动它时,客户端无法连接到它。如果我等待大约一分钟,然后再次尝试连接客户端,它会非常完美。执行ps -A | grep my_server时,我没有发现进程正在运行。然而,如果我试着在大约2分钟内连接,它会很好。

我觉得这很奇怪。

我习惯了Python中有一个稍微类似的问题,在按下Ctrl+C后,我很难连接到端口。在这种情况下,该进程可能仍在运行,我必须手动终止该进程并尝试再次连接(那时它会正常工作)。

有什么代码需要我特别粘贴吗?我接受以下连接:-

NetworkManager* start_listening(char* host, int port) {
  keep_running = true;
  signal(SIGINT, signal_handler);
  int listenfd, connfd, n;
  struct sockaddr_in servaddr, cliaddr;
  socklen_t clilen;
  pid_t pid;
  listenfd = socket(AF_INET, SOCK_STREAM, 0);
  bzero(&servaddr, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  servaddr.sin_port = htons(port);
#ifdef DEBUG
  std::cout << "[+] Starting to listen at port " << port << std::endl;
#endif
#ifdef DEBUG
  std::cout << "[+] Binding to port" << std::endl;
#endif
  bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
#ifdef DEBUG
  std::cout << "[+] Starting to listen" << std::endl;
#endif
  listen(listenfd, 1024);
  clilen = sizeof(cliaddr);
  while ( keep_running ) {
    connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
#ifdef DEBUG
    if ( connfd == -1 ) {
      std::cout << "Yikes got an error with errno = " << errno << std::endl;
    }
    sockaddr_in* pV4Addr = (struct sockaddr_in*)&cliaddr;
    int ipAddr = pV4Addr->sin_addr.s_addr;
    char str[20];
    inet_ntop(AF_INET, &ipAddr, str, 20);
    std::cout << "[+] Incoming connection from " << str << std::endl;
    std::cout << "[+] Using socket " << connfd << std::endl;
#endif
    if ( (pid=fork()) == 0 ) {
      close(listenfd);
      NetworkManager *nm = new NetworkManager(connfd);
      return nm;
    } else {
      close(connfd);
    }
  }
  if (!keep_running) {
    // #TODO kill all children
#ifdef DEBUG
    std::cout << "[+] Killing server" << std::endl;
#endif
    exit(0);
  }
  return 0;
}

问题是您没有检查返回值。例如,绑定。这可能会失败。例如,因为您没有使用REUSEADDR来允许绑定到最近使用的端口。这些事情都有一个暂停,当你提到两分钟后它又能工作时,这是一个彻头彻尾的赠品。但实际上,请检查您的返回值——这毕竟是C!