简体   繁体   中英

select() accepting connections while reading and receiving data from clients

I'm connected to certain client then we're communicating. Another client connects to my server which will instantly output that there's a new connection.. eg Accepting while listening to other clients?.. How can i do that?..

I have already a working one but it only does one thing at a time. When i'm already communicating with my client i can't accept incoming connection or data to other clients. I can only accept new connection or data from other clients when the client i'm communicating is disconnected. how can i do so that it can process both accept and listen to client at the same time. I don't want to use threads.

Here's a part of my code.

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

I've been working on it for two days and still i can't get it. thanks..

Well, to give you an example of a working multi-connection daemon, have a look at this example

If you need a further explanation to go with it, shoot.

Note, the code in that example has been stripped of things like daemon_init() , etc, so just copy-pasting blindly and trying to compile it won't work.

Added setnonblocking() as per request.

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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