select()在从客户端读取和接收数据时接受连接

时间:2012-10-25 01:20:31

标签: c linux sockets

我与某个客户有联系然后我们正在沟通。另一个客户端连接到我的服务器,它将立即输出有一个新连接..例如,在听其他客户端时接受?..我该怎么做?...

我已经有一个工作了,但它一次只做一件事。当我已经与我的客户端通信时,我无法接受传入的连接或数据给其他客户端。当我正在通信的客户端断开连接时,我只能接受来自其他客户端的新连接或数据。我怎么能这样做,它可以同时处理接受和听取客户端。我不想使用线程。

这是我的代码的一部分。

do
{
   fduse = fdin;
   printf("Waiting for Connection\n");
   err = select(sMax + 1, &fduse, NULL, NULL, NULL);
   if (err < 0)
   {
      perror("  select() failed");
      break;
   }
   DescRead = err;
   for (SockStorage = 0; SockStorage <= sMax && DescRead > 0; ++SockStorage)
   {
      if (FD_ISSET(SockStorage, &fduse))
      {
         DescRead -= 1;
         if (SockStorage == socketFd)
         {
            printf("  Listening socket is readable\n");
            do
            {
               NewSFD =
                  accept(socketFd, (struct sockaddr *)&cli_addr, &clilen);
               if (NewSFD < 0)
               {
                  if (errno != EWOULDBLOCK)
                  {
                     perror("  accept() failed");
                     DCSERVER = TRUE;
                  }
                  break;
               }
               if (ClientCount < MAX_CLIENTS)
               {
                  for (loop = 0; loop < MAX_CLIENTS; loop++)
                  {
                     if (Clients[loop].connected_sock < 0)
                     {
                        Clients[loop].connected_sock = NewSFD;
                        break;
                     }
                  }
                  ClientCount++;
               }
               else
               {
                  printf("Maximum Client Reached.\n");
                  char *sendtoclient = "Server full. ";
                  send(NewSFD, sendtoclient, strlen(sendtoclient), 0);
                  close(NewSFD);
                  break;
               }
               ip = ntohl(cli_addr.sin_addr.s_addr);
               printf("  Connection from %d.%d.%d.%d\n",
                  (int)(ip >> 24) & 0xff,
                  (int)(ip >> 16) & 0xff,
                  (int)(ip >> 8) & 0xff, (int)(ip >> 0) & 0xff);
               dlogs(ip);

               FD_SET(NewSFD, &fdin);
               if (NewSFD > sMax)
                  sMax = NewSFD;
            }
            while (NewSFD != -1);
         }
         else
         {
            int d;
            for (d = 0; d < MAX_CLIENTS; d++)
            {
               printf("Descriptor ID: %d\n", Clients[d].connected_sock);
            }

            pfds[0].fd = fd;
            pfds[0].events = POLLIN;
            pfds[1].fd = SockStorage;
            pfds[1].events = POLLIN;
            state = FALSE;
            do
            {
               rc = poll(pfds, 2, -1);
               if (pfds[0].revents & POLLIN)
               {
                  while ((nbytes = read(fd, buf, sizeof (buf) - 1)) > 0)
                  {
                     buf[nbytes] = '\0';
                     printf("%s\n", buf);
                  }
                  pfds[0].events = 0;
                  pfds[1].events = POLLIN | POLLOUT;
               }
               if (pfds[1].revents & POLLIN)
               {
                  err = recv(SockStorage, strbuf, sizeof (strbuf), 0);
                  if (err < 0)
                  {
                     if (errno != EWOULDBLOCK)
                     {
                        perror("  recv() failed");
                        state = TRUE;
                     }
                     break;
                  }
                  if (err == 0)
                  {
                     printf("  Connection closed\n");
                     state = TRUE;
                     break;
                  }
                  dSize = err;
                  printf("  %d bytes received\n", dSize);
               }

               if (pfds[1].revents & POLLOUT)
               {
                  int s;
                  for (s = 0; s < MAX_CLIENTS; s++)
                  {
                     if (Clients[s].connected_sock > 0)
                     {
                        err =
                           send(Clients[s].connected_sock, buf,
                           strlen(buf), 0);
                        if (err < 0)
                        {
                           perror("  send() failed");
                           track = s;
                           state = TRUE;
                           break;
                        }
                     }
                  }
                  pfds[0].events = POLLIN;
                  pfds[1].events = POLLIN;
               }

            }
            while (TRUE);
            fopen("/sockF.txt", "w");
            if (state)
            {
               ClientCount--;
               close(SockStorage);
               FD_CLR(SockStorage, &fdin);
               if (SockStorage == sMax)
               {
                  while (FD_ISSET(sMax, &fdin) == FALSE)
                     sMax -= 1;
               }
            }
         }
      }
   }
} while (DCSERVER == FALSE);
cleanUP(SockStorage, sMax);
}

我已经工作了两天但仍然无法得到它。感谢..

1 个答案:

答案 0 :(得分:0)

那么,为了举例说明一个有效的多连接守护进程,请查看this example

如果您需要进一步解释,请拍摄。

请注意,该示例中的代码已被删除daemon_init()等内容,因此只是盲目地复制粘贴并尝试编译它将无效。

根据请求添加了setnonblocking()

void setnonblocking(sock)
  int sock;
{
  int opts;

  opts = fcntl(sock, F_GETFL);

  if (opts < 0)
    {
      syslog(LOG_ERR, "fcntl(F_GETFL) failed");
      exit(EXIT_FAILURE);
    }

  opts = (opts | O_NONBLOCK);

  if (fcntl(sock, F_SETFL, opts) < 0)
    {
      syslog(LOG_ERR, "fcntl(F_SETFL) failed");
      exit(EXIT_FAILURE);
    }

  return;
}

daemon_init()

int daemon_init(void)
{
  pid_t pid;
  int i;


  if ((pid = fork()) < 0)
    {
      return -1;
    }
  else if (pid != 0)
    {
      exit(0);
    }

  for (i=getdtablesize();i>=0;--i) close(i);
  i = open("/dev/null", O_RDWR); /* open stdin */
  dup(i); /* stdout */
  dup(i); /* stderr */

  setsid();
  return 0;
}