下面的代码来自IBM学习网站,是学习socket通信和select使用的一个很好的源码。
server.c 服务器端
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <sys/ioctl.h> 4 #include <sys/socket.h> 5 #include <sys/time.h> 6 #include <netinet/in.h> 7 #include <errno.h> 8 9 #define SERVER_PORT 12345 10 11 #define TRUE 1 12 #define FALSE 0 13 14 main (int argc, char *argv[]) 15 { 16 int i, len, rc, on = 1; 17 int listen_sd, max_sd, new_sd; 18 int desc_ready, end_server = FALSE; 19 int close_conn; 20 char buffer[80]; 21 struct sockaddr_in addr; 22 struct timeval timeout; 23 fd_set master_set, working_set; 24 25 /*************************************************************/ 26 /* Create an AF_INET stream socket to receive incoming */ 27 /* connections on */ 28 /*************************************************************/ 29 listen_sd = socket(AF_INET, SOCK_STREAM, 0); 30 if (listen_sd < 0) 31 { 32 perror("socket() failed"); 33 exit(-1); 34 } 35 36 /*************************************************************/ 37 /* Allow socket descriptor to be reuseable */ 38 /*************************************************************/ 39 rc = setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, 40 (char *)&on, sizeof(on)); 41 if (rc < 0) 42 { 43 perror("setsockopt() failed"); 44 close(listen_sd); 45 exit(-1); 46 } 47 48 /*************************************************************/ 49 /* Set socket to be non-blocking. All of the sockets for */ 50 /* the incoming connections will also be non-blocking since */ 51 /* they will inherit that state from the listening socket. */ 52 /*************************************************************/ 53 rc = ioctl(listen_sd, FIONBIO, (char *)&on); 54 if (rc < 0) 55 { 56 perror("ioctl() failed"); 57 close(listen_sd); 58 exit(-1); 59 } 60 61 /*************************************************************/ 62 /* Bind the socket */ 63 /*************************************************************/ 64 memset(&addr, 0, sizeof(addr)); 65 addr.sin_family = AF_INET; 66 addr.sin_addr.s_addr = htonl(INADDR_ANY); 67 addr.sin_port = htons(SERVER_PORT); 68 rc = bind(listen_sd, 69 (struct sockaddr *)&addr, sizeof(addr)); 70 if (rc < 0) 71 { 72 perror("bind() failed"); 73 close(listen_sd); 74 exit(-1); 75 } 76 77 /*************************************************************/ 78 /* Set the listen back log */ 79 /*************************************************************/ 80 rc = listen(listen_sd, 32); 81 if (rc < 0) 82 { 83 perror("listen() failed"); 84 close(listen_sd); 85 exit(-1); 86 } 87 88 /*************************************************************/ 89 /* Initialize the master fd_set */ 90 /*************************************************************/ 91 FD_ZERO(&master_set); 92 max_sd = listen_sd; 93 FD_SET(listen_sd, &master_set); 94 95 /*************************************************************/ 96 /* Initialize the timeval struct to 3 minutes. If no */ 97 /* activity after 3 minutes this program will end. */ 98 /*************************************************************/ 99 timeout.tv_sec = 3 * 60; 100 timeout.tv_usec = 0; 101 102 /*************************************************************/ 103 /* Loop waiting for incoming connects or for incoming data */ 104 /* on any of the connected sockets. */ 105 /*************************************************************/ 106 do 107 { 108 /**********************************************************/ 109 /* Copy the master fd_set over to the working fd_set. */ 110 /**********************************************************/ 111 memcpy(&working_set, &master_set, sizeof(master_set)); 112 113 /**********************************************************/ 114 /* Call select() and wait 5 minutes for it to complete. */ 115 /**********************************************************/ 116 printf("listen_sd is %d ",listen_sd); 117 printf("Waiting on select()... "); 118 119 rc = select(max_sd + 1, &working_set, NULL, NULL, &timeout); 120 121 /**********************************************************/ 122 /* Check to see if the select call failed. */ 123 /**********************************************************/ 124 if (rc < 0) 125 { 126 perror(" select() failed"); 127 break; 128 } 129 130 /**********************************************************/ 131 /* Check to see if the 5 minute time out expired. */ 132 /**********************************************************/ 133 if (rc == 0) 134 { 135 printf(" select() timed out. End program. "); 136 break; 137 } 138 139 /**********************************************************/ 140 /* One or more descriptors are readable. Need to */ 141 /* determine which ones they are. */ 142 /**********************************************************/ 143 desc_ready = rc; 144 for (i=0; i <= max_sd && desc_ready > 0; ++i) 145 { 146 /*******************************************************/ 147 /* Check to see if this descriptor is ready */ 148 /*******************************************************/ 149 if (FD_ISSET(i, &working_set)) 150 { 151 /****************************************************/ 152 /* A descriptor was found that was readable - one */ 153 /* less has to be looked for. This is being done */ 154 /* so that we can stop looking at the working set */ 155 /* once we have found all of the descriptors that */ 156 /* were ready. */ 157 /****************************************************/ 158 desc_ready -= 1; 159 160 /****************************************************/ 161 /* Check to see if this is the listening socket */ 162 /****************************************************/ 163 if (i == listen_sd) 164 { 165 printf(" Listening socket is readable "); 166 /*************************************************/ 167 /* Accept all incoming connections that are */ 168 /* queued up on the listening socket before we */ 169 /* loop back and call select again. */ 170 /*************************************************/ 171 do 172 { 173 /**********************************************/ 174 /* Accept each incoming connection. If */ 175 /* accept fails with EWOULDBLOCK, then we */ 176 /* have accepted all of them. Any other */ 177 /* failure on accept will cause us to end the */ 178 /* server. */ 179 /**********************************************/ 180 new_sd = accept(listen_sd, NULL, NULL); 181 if (new_sd < 0) 182 { 183 if (errno != EWOULDBLOCK) 184 { 185 perror(" accept() failed"); 186 end_server = TRUE; 187 } 188 break; 189 } 190 191 /**********************************************/ 192 /* Add the new incoming connection to the */ 193 /* master read set */ 194 /**********************************************/ 195 printf(" New incoming connection - %d ", new_sd); 196 FD_SET(new_sd, &master_set); 197 if (new_sd > max_sd) 198 max_sd = new_sd; 199 200 /**********************************************/ 201 /* Loop back up and accept another incoming */ 202 /* connection */ 203 /**********************************************/ 204 } while (new_sd != -1); 205 } 206 207 /****************************************************/ 208 /* This is not the listening socket, therefore an */ 209 /* existing connection must be readable */ 210 /****************************************************/ 211 else 212 { 213 printf(" Descriptor %d is readable ", i); 214 close_conn = FALSE; 215 /*************************************************/ 216 /* Receive all incoming data on this socket */ 217 /* before we loop back and call select again. */ 218 /*************************************************/ 219 do 220 { 221 /**********************************************/ 222 /* Receive data on this connection until the */ 223 /* recv fails with EWOULDBLOCK. If any other */ 224 /* failure occurs, we will close the */ 225 /* connection. */ 226 /**********************************************/ 227 rc = recv(i, buffer, sizeof(buffer), 0); 228 if (rc < 0) 229 { 230 if (errno != EWOULDBLOCK) 231 { 232 perror(" recv() failed"); 233 close_conn = TRUE; 234 } 235 break; 236 } 237 238 /**********************************************/ 239 /* Check to see if the connection has been */ 240 /* closed by the client */ 241 /**********************************************/ 242 if (rc == 0) 243 { 244 printf(" Connection closed "); 245 close_conn = TRUE; 246 break; 247 } 248 249 /**********************************************/ 250 /* Data was recevied */ 251 /**********************************************/ 252 len = rc; 253 printf(" %d bytes received ", len); 254 255 /**********************************************/ 256 /* Echo the data back to the client */ 257 /**********************************************/ 258 rc = send(i, buffer, len, 0); 259 if (rc < 0) 260 { 261 perror(" send() failed"); 262 close_conn = TRUE; 263 break; 264 } 265 266 } while (TRUE); 267 268 /*************************************************/ 269 /* If the close_conn flag was turned on, we need */ 270 /* to clean up this active connection. This */ 271 /* clean up process includes removing the */ 272 /* descriptor from the master set and */ 273 /* determining the new maximum descriptor value */ 274 /* based on the bits that are still turned on in */ 275 /* the master set. */ 276 /*************************************************/ 277 if (close_conn) 278 { 279 close(i); 280 FD_CLR(i, &master_set); 281 if (i == max_sd) 282 { 283 while (FD_ISSET(max_sd, &master_set) == FALSE) 284 max_sd -= 1; 285 } 286 } 287 } /* End of existing connection is readable */ 288 } /* End of if (FD_ISSET(i, &working_set)) */ 289 } /* End of loop through selectable descriptors */ 290 291 } while (end_server == FALSE); 292 293 /*************************************************************/ 294 /* Cleanup all of the sockets that are open */ 295 /*************************************************************/ 296 for (i=0; i <= max_sd; ++i) 297 { 298 if (FD_ISSET(i, &master_set)) 299 close(i); 300 } 301 }
client.c 客户端
1 /**************************************************************************/ 2 /* Generic client example is used with connection-oriented server designs */ 3 /**************************************************************************/ 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <sys/socket.h> 7 #include <netinet/in.h> 8 9 #define SERVER_PORT 12345 10 11 main (int argc, char *argv[]) 12 { 13 int len, rc; 14 int sockfd; 15 char send_buf[80]; 16 char recv_buf[80]; 17 struct sockaddr_in addr; 18 19 /*************************************************/ 20 /* Create an AF_INET stream socket */ 21 /*************************************************/ 22 sockfd = socket(AF_INET, SOCK_STREAM, 0); 23 if (sockfd < 0) 24 { 25 perror("socket"); 26 exit(-1); 27 } 28 29 /*************************************************/ 30 /* Initialize the socket address structure */ 31 /*************************************************/ 32 memset(&addr, 0, sizeof(addr)); 33 addr.sin_family = AF_INET; 34 addr.sin_addr.s_addr = htonl(INADDR_ANY); 35 addr.sin_port = htons(SERVER_PORT); 36 37 /*************************************************/ 38 /* Connect to the server */ 39 /*************************************************/ 40 rc = connect(sockfd, 41 (struct sockaddr *)&addr, 42 sizeof(struct sockaddr_in)); 43 if (rc < 0) 44 { 45 perror("connect"); 46 close(sockfd); 47 exit(-1); 48 } 49 printf("Connect completed.socketfd is %d .rc is %d ",sockfd,rc); 50 51 /*************************************************/ 52 /* Enter data buffer that is to be sent */ 53 /*************************************************/ 54 printf("Enter message to be sent: "); 55 gets(send_buf); 56 57 /*************************************************/ 58 /* Send data buffer to the worker job */ 59 /*************************************************/ 60 len = send(sockfd, send_buf, strlen(send_buf) + 1, 0); 61 if (len != strlen(send_buf) + 1) 62 { 63 perror("send"); 64 close(sockfd); 65 exit(-1); 66 } 67 printf("%d bytes sent ", len); 68 69 /*************************************************/ 70 /* Receive data buffer from the worker job */ 71 /*************************************************/ 72 len = recv(sockfd, recv_buf, sizeof(recv_buf), 0); 73 if (len != strlen(send_buf) + 1) 74 { 75 perror("recv"); 76 close(sockfd); 77 exit(-1); 78 } 79 printf("%d bytes received ", len); 80 81 /*************************************************/ 82 /* Close down the socket */ 83 /*************************************************/ 84 close(sockfd); 85 }