服务端代码:
myselect.c
1 #include <stdio.h> 2 #include <netinet/in.h> 3 #include <arpa/inet.h> 4 #include <sys/socket.h> 5 #include <sys/types.h> 6 #include <sys/stat.h> 7 #include <string.h> 8 #include <stdlib.h> 9 #include <unistd.h> 10 11 12 #define ARRAY_SIZE 1024 13 14 15 /* 使用说明 */ 16 void usage(const char* proc) 17 { 18 printf("%s usage : [server_ip] [ server_port] ", proc); 19 } 20 21 22 /* 初始化一个socket连接 */ 23 int init_sock(const char* _ip, int _port) 24 { 25 int sock = socket(AF_INET, SOCK_STREAM, 0); 26 if(sock < 0) 27 { 28 perror("socket"); 29 exit(2); 30 } 31 32 int flg = 1; 33 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &flg, sizeof(flg)); 34 struct sockaddr_in local; 35 local.sin_family = AF_INET; 36 local.sin_port = htons(_port); 37 local.sin_addr.s_addr = inet_addr(_ip); 38 39 if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0) 40 { 41 perror("bind"); 42 exit(3); 43 } 44 45 if(listen(sock , 10) < 0) 46 { 47 perror("listen"); 48 exit(4); 49 } 50 51 return sock; 52 } 53 54 /* 等待事件发生并处理 */ 55 void run_select(int listen_sock) 56 { 57 58 int array_fds[ARRAY_SIZE]; /* 保存所有关心的描述符 */ 59 array_fds[0] = listen_sock; /* 将listen_sock 保存*/ 60 61 /* 初始化为 array_fds */ 62 int idx_init = 1; 63 for(idx_init = 1; idx_init < ARRAY_SIZE; ++idx_init) 64 array_fds[idx_init] = -1; 65 66 fd_set rfds; /* 关心的读事件描述符集 */ 67 fd_set wfds; /* 关心的写事件描述符集 */ 68 int max_fd = -1; 69 70 struct timeval _timeout = {1, 0}; 71 72 while(1) 73 { 74 max_fd = -1; 75 _timeout.tv_sec = 1; 76 FD_ZERO(&rfds); 77 FD_ZERO(&wfds); 78 79 /* 一. 将数组中存储的描述符,添加到关心的集合中 80 * 并找出其中最大的描述符, 81 */ 82 int idx_add = 1; 83 for(idx_add = 0; idx_add < ARRAY_SIZE; idx_add++) 84 { 85 if(array_fds[idx_add] > 0) 86 { 87 FD_SET(array_fds[idx_add], &rfds); 88 FD_SET(array_fds[idx_add], &wfds); 89 if(array_fds[idx_add] > max_fd) 90 max_fd = array_fds[idx_add]; 91 92 } 93 } 94 /* 二. 检测select的返回情况*/ 95 int select_ret = select(max_fd+1, &rfds, &wfds, NULL, &_timeout); 96 switch( select_ret ) 97 { 98 case 0: 99 printf("timeout "); 100 break; 101 case -1: 102 perror("select "); 103 break; 104 default: 105 { 106 /* 遍历数组,检测事件发生的描述符,并响应 */ 107 int idx_check = 0; 108 for(idx_check = 0; idx_check < ARRAY_SIZE; ++idx_check) 109 { 110 if(array_fds[idx_check] < 0) 111 continue; 112 113 if(idx_check == 0 && FD_ISSET(array_fds[idx_check], &rfds) ) 114 { /* listensock 有数据来,表示有新的连接请求 */ 115 struct sockaddr_in client; 116 socklen_t len = sizeof(client); 117 118 int new_sock = accept(listen_sock, (struct sockaddr*)&client, &len); 119 if(new_sock > 0) 120 { 121 printf("新的连接请求来自: ip = %s, port = %d ",inet_ntoa(client.sin_addr), ntohs(client.sin_port)); 122 123 /* 在数组中找到未被占用的描述符位置,并保存新连接的描述符 */ 124 int idx_find = 0; 125 for(idx_find = 1; idx_find < ARRAY_SIZE; ++idx_find) 126 { 127 if(array_fds[idx_find] < 0) 128 { 129 array_fds[idx_find] = new_sock; 130 break; 131 } 132 } 133 if(idx_find == ARRAY_SIZE) 134 close(new_sock); 135 } 136 } // << end if idx_check == 0 && FD_ISSET -- rfds>> 137 else if( idx_check != 0 && FD_ISSET(array_fds[idx_check], &rfds) ) 138 { /* 其余描述符有数据来*/ 139 140 char buf[ 1024]; 141 memset(buf, '