socket中select的使用源码

 

下面的代码来自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()...\n");
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.\n");
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\n");
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\n", 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\n", 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\n");
245                      close_conn = TRUE;
246                      break;
247                   }
248 
249                   /**********************************************/
250                   /* Data was recevied                          */
251                   /**********************************************/
252                   len = rc;
253                   printf("  %d bytes received\n", 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 \n",sockfd,rc);
50 
51    /*************************************************/
52    /* Enter data buffer that is to be sent          */
53    /*************************************************/
54    printf("Enter message to be sent:\n");
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\n", 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\n", len);
80 
81    /*************************************************/
82    /* Close down the socket                         */
83    /*************************************************/
84    close(sockfd);
85 }
posted @ 2013-11-27 21:59  lvsj  阅读(6342)  评论(0编辑  收藏  举报