Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 作为后台进程运行时,我的服务器不接受连接_C_Sockets_Tcp_Client - Fatal编程技术网

C 作为后台进程运行时,我的服务器不接受连接

C 作为后台进程运行时,我的服务器不接受连接,c,sockets,tcp,client,C,Sockets,Tcp,Client,我用C写了一个简单的服务器,它回答8888端口的连接。它工作得很好…直到我尝试将其作为后台进程运行 当我像这样运行它时 $ ./server 然后尝试与客户机连接,工作正常。当我尝试像这样运行它时: $ ./server & 或者如果我像这样运行它 $ ./server 然后用CTRL+z将其分离,并尝试与我获得的客户端连接 Connection Refused 以前有人遇到过这个问题吗?如果能找到解决办法,我将不胜感激 以下是根据请求接受调用的代码: char remot

我用C写了一个简单的服务器,它回答8888端口的连接。它工作得很好…直到我尝试将其作为后台进程运行

当我像这样运行它时

$ ./server
然后尝试与客户机连接,工作正常。当我尝试像这样运行它时:

$ ./server &
或者如果我像这样运行它

$ ./server 
然后用CTRL+z将其分离,并尝试与我获得的客户端连接

Connection Refused
以前有人遇到过这个问题吗?如果能找到解决办法,我将不胜感激

以下是根据请求接受调用的代码:

  char remoteIP[ INET6_ADDRSTRLEN ];
  int yes=1;    /* for setsockopt() SO_REUSEADDR, below */
  int i, rv;
  struct addrinfo hints, *ai, *p;

  FD_ZERO( &master );  /* clear the master and temp sets */
  FD_ZERO( &read_fds );

  /* get us a socket and bind it */
  memset( &hints, 0, sizeof hints );
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE;

  if ( ( rv = getaddrinfo( NULL, URL_PORT, &hints, &ai ) ) != 0 )
  {
    /* fprintf( stderr, "selectserver: %s\n", gai_strerror( rv ) ); */
    exit( 1 );
  }

  /* printf( "Listening on port %s for URLs...\n", URL_PORT ); */
  for( p = ai; p != NULL; p = p->ai_next )
  {
    listener = socket( p->ai_family, p->ai_socktype, p->ai_protocol );
    if ( listener < 0 )
    {
      continue;
    }

    /* lose the pesky "address already in use" error message */
    setsockopt( listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof( int ) );
    if ( bind( listener, p->ai_addr, p->ai_addrlen) < 0 )
    {
      close( listener );
      continue;
    }
    break;
  }

  /* if we got here, it means we didn't get bound */
  if ( p == NULL )
  {
    /* fprintf( stderr, "selectserver: failed to bind\n" ); */
    exit( 2 );
  }

  freeaddrinfo( ai ); /* all done with this */

  /* listen */
  if ( listen( listener, 10 ) == -1 )
  {
    perror( "listen" );
    exit( 3 );
  }

  /* add the listener to the master set */
  FD_SET( listener, &master );

  /* keep track of the biggest file descriptor */
  fdmax = listener; /* so far, it's this one */

  /* main loop */
  for( ; ; ) {


    for( i = 0; i <= fdmax; i++ )
    {
      if ( SOCKETS[ i ].in_progress )
      {
        if ( pthread_join( SOCKETS[ i ].thread, NULL ) != 0 )
        {
          /* fprintf( stderr, "Error terminating thread %i\n", i ); */
        }
        else
        {
          SOCKETS[ i ].in_progress = FALSE;
        }
      }
    }

    read_fds = master; /* copy it */

    if ( select( fdmax + 1, &read_fds, NULL, NULL, NULL ) == -1 )
    {
      perror( "select" );
      exit(4);
    }

    /* run through the existing connections looking for data to read */
    for( i = 0; i <= fdmax; i++ ) {

      if ( FD_ISSET( i, &read_fds ) && SOCKETS[ i ].in_progress == FALSE )
      {
        /* we got one!! */
        if ( i == listener )
        {
          /* handle new connections */
          addrlen = sizeof remoteaddr;
          newfd = accept( listener, ( struct sockaddr * ) &remoteaddr, &addrlen );
          if ( newfd == -1 )
          {
            perror( "accept" );
          }
          else
          {
            FD_SET( newfd, &master ); /* add to master set */

            if ( newfd > fdmax )
            {  /* keep track of the max */
              fdmax = newfd;
            }

            /*
            printf( 
              "selectserver: new connection from %s on socket %d\n",
              inet_ntop( remoteaddr.ss_family, get_in_addr( ( struct sockaddr* ) &remoteaddr ), remoteIP, INET6_ADDRSTRLEN ), newfd );
            */
          }
        }

您的进程从其控制终端读取或写入数据,因此当您在后台使用&运行它时,它会被SIGTTIN或sigttoo停止

有关摘录自:

只允许前台进程读取或写入 航空站尝试从写入到读取的后台进程 终端发送一个SIGTTIN SIGTOU信号 驱动程序,除非被捕获,否则将暂停进程

SIGTTOU的发送由一个默认为off的标志控制,因此您的问题可能是由从控制终端读取引起的。如果要防止后台进程写入终端,即重新启用向尝试后台写入的进程发送SIGTOU,请使用以下命令:

stty tostop
bg %1
您可以通过以下操作恢复到默认行为:

stty -tostop
当按下Ctrl+Z键时,会将SIGTSTP发送到进程。此信号的默认配置也是停止进程。如果要使进程继续在后台运行,请使用以下命令:

stty tostop
bg %1
请注意,在您的情况下,工作编号可能不同。使用job命令进行检查


请注意,与SIGSTOP不同,如果您不喜欢此行为,则这三个信号可以由您的进程处理或忽略。读/写系统调用随后将返回EINTR而不是阻塞。

您的进程从其控制终端读取或写入,因此当您在后台使用&运行它时,它将被SIGTTIN或SIGTOU停止

有关摘录自:

只允许前台进程读取或写入 航空站尝试从写入到读取的后台进程 终端发送一个SIGTTIN SIGTOU信号 驱动程序,除非被捕获,否则将暂停进程

SIGTTOU的发送由一个默认为off的标志控制,因此您的问题可能是由从控制终端读取引起的。如果要防止后台进程写入终端,即重新启用向尝试后台写入的进程发送SIGTOU,请使用以下命令:

stty tostop
bg %1
您可以通过以下操作恢复到默认行为:

stty -tostop
当按下Ctrl+Z键时,会将SIGTSTP发送到进程。此信号的默认配置也是停止进程。如果要使进程继续在后台运行,请使用以下命令:

stty tostop
bg %1
请注意,在您的情况下,工作编号可能不同。使用job命令进行检查


请注意,与SIGSTOP不同,如果您不喜欢此行为,则这三个信号可以由您的进程处理或忽略。读/写系统调用随后将返回EINTR而不是阻塞。

如果在服务器处于后台时运行ps,您是否看到它正在运行?是的,我可以看到它正在运行。您是否能够在执行接受调用的地方发布代码和某些上下文?已发布。您可能会从beej的指南中注意到一些相似之处。Ctrl+Z会在Linux上挂起该过程,因此这并不奇怪。然而,令人惊讶的是,./server&version无法工作。如果您取消对printfs的注释,您在终端中会看到什么输出?如果您在服务器处于后台时运行ps,您是否看到它正在运行?是的,我可以看到它正在运行。您是否能够发布代码和执行accept调用的某个上下文?已发布。您可能会从beej的指南中注意到一些相似之处。Ctrl+Z会在Linux上挂起该过程,因此这并不奇怪。然而,令人惊讶的是,./server&version无法工作。如果取消对printf的注释,您在终端中看到了什么输出?printf是写入终端的方法吗?getc怎么样?我想那些只是用了标准输入法和标准输出法。是吗?我取消了一个getc呼叫,解决了这个问题。你太棒了!printf是写入终端的方法吗?getc怎么样?我想那些只是用了标准输入法和标准输出法。是吗?我取消了一个getc呼叫,解决了这个问题。你太棒了!