简体   繁体   English

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

[英]Clients unable to connect after server shutdown and restart

I have a problem with my C++ networking code(a test server that receives strings and displays it). 我的C ++网络代码(接收并显示字符串的测试服务器)有问题。 Occasionally, when I turn off my server(Ctrl C) and then restart it, clients fail to connect to it. 有时,当我关闭服务器(Ctrl C)然后重新启动服务器时,客户端无法连接到它。 If I wait for around a minute and try connecting with a client again, it works perfect. 如果我等待大约一分钟,然后尝试再次与客户联系,则效果很好。 Doing a ps -A | grep my_server ps -A | grep my_server ps -A | grep my_server I don't find the process running. ps -A | grep my_server我找不到正在运行的进程。 However, if I'd try to connect in about 2 minutes it would work just fine. 但是,如果我尝试在2分钟左右内连接,就可以正常工作。

I find this rather strange. 我觉得这很奇怪。

I'm used to a slightly similar problem in Python, where I have trouble connecting to a port after pressing Ctrl+C. 我曾经在Python中遇到过类似的问题,在按Ctrl + C后无法连接到端口。 In that case, the process might still be running and I'd have to manually kill the process and try connecting again(and it would work just fine then). 在这种情况下,该进程可能仍在运行,我必须手动终止该进程,然后尝试再次连接(然后它将正常工作)。

Is there any code that you'd like me to paste in particular? 您是否要特别粘贴任何代码? I'm accepting the connections as follows :- 我接受以下连接:-

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

The problem is that you're not checking your return values. 问题是您没有检查返回值。 For example, to bind. 例如绑定。 Which could be failing. 这可能会失败。 For example, because you aren't using REUSEADDR to allow binding to a port which was recently in use. 例如,因为您没有使用REUSEADDR来允许绑定到最近使用的端口。 There's a timeout on these things, and that was a dead giveaway when you mentioned that it works again after two minutes. 这些事情有一个超时时间,当您提到两分钟后它又能正常工作时,那真是一个致命的礼物。 But really, check your return values--this is C after all! 但实际上,请检查您的返回值-毕竟是C!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM