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

时间:2013-12-12 12:08:26

标签: c++ sockets network-programming

我的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;
}

1 个答案:

答案 0 :(得分:1)

问题是您没有检查您的返回值。例如,要绑定。哪个可能会失败。例如,因为您没有使用REUSEADDR来允许绑定到最近使用的端口。这些事情已经超时了,当你提到它在两分钟后再次运作时,这是一个死的赠品。但实际上,请检查您的返回值 - 毕竟这是C!