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 |
| | |
| | | #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)
|
| | | {
|
| | |
| | | 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[] =
|
| | | {
|
| | |
| | | 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 */
|
| | |
| | | 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;
|
| | | }
|
| | |
|
| | |
| | | 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;
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | |
|