APUE Learning Example Source Code
Guo Wenxue
2018-11-26 958940edc920cda07bd217027477f916e40a252e
ch5_multiplexing/socket_server_select_array.c
copy from ch5_multiplexing/socket_server_select.c copy to ch5_multiplexing/socket_server_select_array.c
File was copied from ch5_multiplexing/socket_server_select.c
@@ -13,20 +13,11 @@
#include <arpa/inet.h>
#include <netinet/in.h> 
typedef struct link_node_s
{
    int                   fd;
    struct link_node_s   *next;
} link_node_t;
#define ARRAY_SIZE(x)       (sizeof(x)/sizeof(x[0]))
static inline void msleep(unsigned long ms);
static inline void print_usage(char *progname);
int socket_server_init(char *listen_ip, int listen_port);
int add_fd_list(link_node_t  **head, int fd);
link_node_t *list_remove_node(link_node_t  **head, link_node_t *node);
int main(int argc, char **argv)
{
@@ -34,15 +25,14 @@
    int                       serv_port = 0;
    int                       daemon_run = 0;
    char                     *progname = NULL;
    pthread_t                 tid;
    int                       opt;
    fd_set                    rdset; 
    link_node_t              *client_list = NULL; /* client fd link list, we will not use arrary for it get max client limite */
    link_node_t              *node;
    int                       rv;
    int                       i;
    int                       i, j;
    int                       found;
    int                       maxfd=0;
    char                      buf[1024];
    int                       fds_array[1024];
    struct option             long_options[] = 
    {   
@@ -96,17 +86,23 @@
        daemon(0, 0);
    }
    printf("add listen socket[%d] into client list\n", listenfd );
    add_fd_list(&client_list, listenfd);
    for(i=0; i<ARRAY_SIZE(fds_array) ; i++)
    {
       fds_array[i]=-1;
    }
    fds_array[0] = listenfd;
    for ( ; ; ) 
    {
        FD_ZERO(&rdset);
          for( node=client_list; node!=NULL; node=node->next )
          for(i=0; i<ARRAY_SIZE(fds_array) ; i++)
   {
       //printf("Add socket[%d] in select readset\n", node->fd);
       maxfd = node->fd>maxfd ? node->fd : maxfd;
       FD_SET(node->fd, &rdset);
       if( fds_array[i] < 0 )
          continue;
       maxfd = fds_array[i]>maxfd ? fds_array[i] : maxfd;
       FD_SET(fds_array[i], &rdset);
   }
   /* program will blocked here */
@@ -131,52 +127,58 @@
                continue;
            }
            printf("accept new client[%d] and add it into client list\n", connfd );
            add_fd_list(&client_list, connfd);
       found = 0;
       for(i=0; i<ARRAY_SIZE(fds_array) ; i++)
       {
           if( fds_array[i] < 0 )
      {
         printf("accept new client[%d] and add it into array\n", connfd );
         fds_array[i] = connfd;
         found = 1;
         break;
      }
       }
       if( !found )
       {
      printf("accept new client[%d] but full, so refuse it\n", connfd);
      close(connfd);
       }
        }
        else /* data arrive from already connected client */
        {
       node = client_list;
              while( node != NULL )
       for(i=0; i<ARRAY_SIZE(fds_array); i++)
       {
      if( !FD_ISSET(node->fd, &rdset) )
      {
         node = node->next;
         continue;
      }
      if( fds_array[i]<0 || !FD_ISSET(fds_array[i], &rdset) )
         continue;
                if( (rv=read(node->fd, buf, sizeof(buf))) <= 0)
                if( (rv=read(fds_array[i], buf, sizeof(buf))) <= 0)
                {
                   printf("socket[%d] read failure or get disconncet.\n", node->fd);
         /* list_remove_node will return the previous node */
         node = list_remove_node(&client_list, node);
                   printf("socket[%d] read failure or get disconncet.\n", fds_array[i]);
         close(fds_array[i]);
         fds_array[i] = -1;
      }
      else
      {
          printf("socket[%d] read get %d bytes data\n", node->fd, rv);
          printf("socket[%d] read get %d bytes data\n", fds_array[i], rv);
          /* convert letter from lowercase to uppercase */
          for(i=0; i<rv; i++)
         buf[i]=toupper(buf[i]);
          for(j=0; j<rv; j++)
         buf[j]=toupper(buf[j]);
                    if( write(node->fd, buf, rv) < 0 )
                    if( write(fds_array[i], buf, rv) < 0 )
          {
              printf("socket[%d] write failure: %s\n", node->fd, strerror(errno));
                /* list_remove_node will return the previous node */
              node = list_remove_node(&client_list, node);
              printf("socket[%d] write failure: %s\n", fds_array[i], strerror(errno));
                close(fds_array[i]);
                fds_array[i] = -1;
          }
      }
      if( node != NULL )
      {
          node = node->next;
      }
            } /* while( node != NULL ) */
            }
        }
    }
CleanUp:
    close(listenfd);  /* We must close socket File Description when program exit*/
    close(listenfd);
    return 0;
}
@@ -265,62 +267,5 @@
        rv = listenfd;
    return rv;
}
int add_fd_list(link_node_t  **head, int fd)
{
    link_node_t          *node;
    link_node_t          *tmp;
    if( NULL == (node=(link_node_t *)malloc(sizeof(*node))) )
    {
        printf("malloc for new node failure\n");
        return -1;
    }
    memset(node, 0, sizeof(*node));
    node->fd = fd;
    node->next = NULL;
    if( *head == NULL )
    {
        *head = node;
        return 0;
    }
    tmp = *head;
    while( tmp->next != NULL )
    {
        tmp=tmp->next;
    }
    tmp->next = node;
}
/* list_remove_node will return the previous node */
link_node_t *list_remove_node(link_node_t  **head, link_node_t *node)
{
    link_node_t         *prev;
    close(node->fd);
    if( node == *head )
    {
    *head = NULL;
    free(node);
    return NULL;
    }
    else
    {
        for(prev=*head; prev!=NULL; prev=prev->next)
        {
      if(prev->next == node)
      {
          prev->next = node->next;
          free(node);
          return prev;
      }
          }
    }
}