Changes between Version 6 and Version 7 of Docs/Prog/Manual/DeviceSupport/Network


Ignore:
Timestamp:
01/13/10 16:20:58 (15 years ago)
Author:
Don Wilson
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Docs/Prog/Manual/DeviceSupport/Network

    v6 v7  
    104104
    105105{{{
    106 //============================================================================
    107 // Name        : tcpip_server.cpp
    108 // Author      : Don Wilson
    109 // Version     :
    110 // Copyright   : Cardinal Scale Mfg
    111 // Description : TCP/IP Server Demo
    112 //============================================================================
     106// TCP/IP Server Demo
    113107
    114108#include <stdio.h>
     
    136130using namespace std;
    137131
     132const int BUFSIZE = 30;
     133
     134// To allow for multiple-byte requests from clients we have to keep a separate receive buffer for each client
     135struct client_info
     136{
     137   int socket;
     138   char buf[BUFSIZE];
     139   int pos;
     140};
     141
    138142// Dynamic list to keep track of connected clients
    139 vector<int> client_list;
     143vector<client_info> client_list;
    140144
    141145int server_s;
     
    147151int ServerProcess(void)
    148152{
    149         int i;
    150         int client_s;
    151         struct sockaddr_in addr;
    152         socklen_t socklen = sizeof(addr);
    153 
    154         // Check for new client connections
    155         client_s = accept(server_s, (sockaddr*)&addr, &socklen);
    156         if(client_s >= 0)
    157         {
    158                 char szIP[INET_ADDRSTRLEN];
    159 
    160                 inet_ntop(AF_INET, &addr.sin_addr, szIP, INET_ADDRSTRLEN);
    161 
    162                 printf("TCP/IP server connection from %s socket %d\r\n", szIP, client_s);
    163 
    164             /* nonblocking socket */
    165             if (fcntl(client_s, F_SETFL, O_NONBLOCK) == -1)
    166                 {
    167                 printf("fcntl: unable to set new socket to non-block\r\n");
    168                 close(client_s);
    169             }
    170             else
    171             {
    172                 client_list.push_back(client_s);
    173             }
    174         }
    175 
    176         if(client_list.size() > 0)
    177         {
    178                 fd_set rfds;
    179                 FD_ZERO(&rfds);
    180                 int nMaxfd = 0;
    181                 for(i = 0; i < (int)client_list.size(); i++)
    182                 {
    183                         FD_SET(client_list[i], &rfds);
    184                         if(client_list[i] > nMaxfd)
    185                                 nMaxfd = client_list[i];
    186                 }
    187 
    188                 struct timeval tv;
    189                 tv.tv_sec = 0;
    190                 tv.tv_usec = 0;
    191 
    192                 int retval = select(nMaxfd + 1, &rfds, NULL, NULL, &tv);
    193                 if(retval == -1)
    194                         printf("select return -1\r\n");
    195                 else if(retval > 0)
    196                 {
    197                         printf("select returned %d\r\n", retval);
    198 
    199                         int rcvlen;
    200                         char data[20], sendbuf[50];
    201                         int z;
    202                         int remove = -1;
    203 
    204                         // Process all connected clients
    205                         for(i = 0; i < (int)client_list.size(); i++)
    206                         {
    207                                 if(FD_ISSET(client_list[i], &rfds))
    208                                 {
    209                                         rcvlen = recv(client_list[i], data, sizeof(data), 0);
    210                                         for(z = 0; z < rcvlen; z++)
    211                                         {
    212                                                 if(data[z] == 0x05)  // ENQ = CTRL-E received
    213                                                 {
    214                                                         // Send response to client
    215                                                         time_t rawtime;
    216                                                         struct tm *timeinfo;
    217                                                         time(&rawtime);
    218                                                         timeinfo = localtime(&rawtime);
    219 
    220                                                         sprintf(sendbuf, "Server time is: %02d:%02d:%02d ",
    221                                                                         timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
    222 
    223                                                         send(client_list[i], sendbuf, strlen(sendbuf), 0);
    224                                                 }
    225                                         }
    226                                         if(rcvlen <= 0)
    227                                         {
    228                                                 printf("recv Error %d\r\n", rcvlen);
    229                                                 remove = i;
    230                                         }
    231                                 }
    232                         }
    233                         if(remove >= 0)
    234                         {
    235                                 printf("Removing %d client socket %d\r\n", remove, client_list[remove]);
    236                                 client_list.erase(client_list.begin() + remove);
    237                         }
    238                 }
    239         }
    240         return 0;
     153   int i;
     154   int client_s;
     155   struct sockaddr_in addr;
     156   socklen_t socklen = sizeof(addr);
     157
     158   // Check for new client connections
     159   client_s = accept(server_s, (sockaddr*)&addr, &socklen);
     160   if(client_s >= 0)
     161   {
     162      char szIP[INET_ADDRSTRLEN];
     163      inet_ntop(AF_INET, &addr.sin_addr, szIP, INET_ADDRSTRLEN);
     164
     165      printf("TCP/IP server connection from IP %s socket %d\r\n", szIP, client_s);
     166
     167      /* nonblocking socket */
     168      if(fcntl(client_s, F_SETFL, O_NONBLOCK) == -1)
     169      {
     170         printf("fcntl: unable to set new socket to non-block\r\n");
     171         close(client_s);
     172      }
     173      else
     174      {
     175         // Add client information to list of connected clients
     176         client_info info;
     177         info.socket = client_s;
     178         info.pos = 0;
     179         client_list.push_back(info);
     180      }
     181   }
     182
     183   // Service any connected clients
     184   if(client_list.size() > 0)
     185   {
     186      struct timeval tv;
     187      tv.tv_sec = 0;
     188      tv.tv_usec = 0;
     189
     190      // Load up structure for "select" statement to check for receive data from all connected clients
     191      fd_set rfds;
     192      FD_ZERO(&rfds);
     193      int nMaxfd = 0;
     194      for(i = 0; i < (int)client_list.size(); i++)
     195      {
     196         FD_SET(client_list[i].socket, &rfds);
     197         if(client_list[i].socket > nMaxfd)
     198            nMaxfd = client_list[i].socket;
     199      }
     200
     201      int retval = select(nMaxfd + 1, &rfds, NULL, NULL, &tv);
     202      if(retval == -1)
     203      {
     204         printf("select return -1\r\n");
     205      }
     206      else if(retval > 0)
     207      {
     208         int rcvlen;
     209         char data[20], sendbuf[50];
     210         int z;
     211         int remove = -1;
     212
     213         // Loop through array of all connected clients
     214         for(i = 0; i < (int)client_list.size(); i++)
     215         {
     216            // Select statement will have loaded rfds to identify which clients have data available to read from
     217            if(FD_ISSET(client_list[i].socket, &rfds))
     218            {
     219               rcvlen = recv(client_list[i].socket, data, sizeof(data), 0);
     220               // Loop through bytes received from this client
     221               for(z = 0; z < rcvlen; z++)
     222               {
     223                  // If ENTER we have completed message - otherwise add character to the client read buffer
     224                  if(data[z] == '\r')
     225                  {
     226                     // Must terminate the string
     227                     client_list[i].buf[client_list[i].pos] = '\0';
     228                     printf("Socket %d message [%s]\r\n", client_list[i].socket, client_list[i].buf);
     229
     230                     // In this sample we check for "TIME<CR>" received and respond with the server time
     231                     if(!strcmp(client_list[i].buf, "TIME"))
     232                     {
     233                        // Get current time
     234                        time_t rawtime;
     235                        struct tm *timeinfo;
     236                        time(&rawtime);
     237                        timeinfo = localtime(&rawtime);
     238
     239                        // Format time into string
     240                        sprintf(sendbuf, "Server time is: %02d:%02d:%02d ",
     241                           timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
     242
     243                        // Send to client
     244                        send(client_list[i].socket, sendbuf, strlen(sendbuf), 0);
     245                     }
     246
     247                     // Reset the buffer position for the next request
     248                     client_list[i].pos = 0;
     249                  }
     250                  else
     251                  {
     252                     // Add character to buffer
     253                     client_list[i].buf[client_list[i].pos++] = data[z];
     254
     255                     // In case of overflow reset position to prevent overwriting memory and crashing
     256                     if(client_list[i].pos >= BUFSIZE)
     257                        client_list[i].pos = 0;
     258                  }
     259               }
     260               if(rcvlen <= 0)
     261               {
     262                  // If the receive length is zero or negative indicates an error - we lost the connection
     263                  // Set variable remove to indicate this client should be removed
     264                  printf("recv Error %d\r\n", rcvlen);
     265                  remove = i;
     266               }
     267            }
     268         }
     269         if(remove >= 0)
     270         {
     271            // If a client disconnected remove it from the list
     272            printf("Removing %d client socket %d\r\n", remove, client_list[remove].socket);
     273            client_list.erase(client_list.begin() + remove);
     274         }
     275      }
     276   }
     277   return 0;
    241278}
    242279
    243280int main()
    244281{
    245 
    246         server_s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    247         if(server_s == -1)
    248         {
    249                 printf("unable to create socket\r\n");
    250                 return -1;
    251         }
    252 
    253     /* server socket is nonblocking */
    254     if (fcntl(server_s, F_SETFL, O_NONBLOCK) == -1)
    255     {
    256             printf("fcntl: unable to set server socket to nonblocking");
    257             return -1;
    258     }
    259 
    260  //   /* close server socket on exec so CGIs can't write to it */
    261 //      if (fcntl(server_s, F_SETFD, 1) == -1) {
    262  //       printf("can't set close-on-exec on server socket!");
    263 //      }
    264 
    265     /* reuse socket addr */
    266         if ((setsockopt(server_s, SOL_SOCKET, SO_REUSEADDR, (void *) &sock_opt, sizeof (sock_opt))) == -1)
    267         {
    268         printf("setsockopt");
    269         }
    270 
    271 
    272         struct sockaddr_in server_sockaddr;
    273         memset(&server_sockaddr, 0, sizeof server_sockaddr);
    274         server_sockaddr.sin_family = PF_INET;
    275 
    276         server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    277 
    278         server_sockaddr.sin_port = htons(nPort);
    279 
    280         if(bind(server_s, (struct sockaddr *) &server_sockaddr, sizeof (server_sockaddr)) == -1)
    281         {
    282                 printf("Unable to bind\r\n");
    283                 return -1;
    284         }
    285 
    286         if(listen(server_s, 10) == -1)
    287         {
    288                 printf("unable to listen");
    289         }
    290 
    291         while(1)
    292         {
    293                 ServerProcess();
    294         }
    295 
    296         return 0;
     282   // Create the server socket
     283   server_s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
     284   if(server_s == -1)
     285   {
     286      printf("unable to create socket\r\n");
     287      return -1;
     288   }
     289
     290   // Set server socket to be nonblocking
     291   if(fcntl(server_s, F_SETFL, O_NONBLOCK) == -1)
     292   {
     293      printf("fcntl: unable to set server socket to nonblocking");
     294      return -1;
     295   }
     296
     297   // Set server to reuse socket addresses
     298   if((setsockopt(server_s, SOL_SOCKET, SO_REUSEADDR, (void *) &sock_opt, sizeof (sock_opt))) == -1)
     299   {
     300      printf("setsockopt");
     301   }
     302
     303   // Prepare sockaddr structure before binding
     304   struct sockaddr_in server_sockaddr;
     305   memset(&server_sockaddr, 0, sizeof server_sockaddr);
     306   server_sockaddr.sin_family = PF_INET;
     307   server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
     308   server_sockaddr.sin_port = htons(nPort);
     309
     310   // Bind the socket address
     311   if(bind(server_s, (struct sockaddr *) &server_sockaddr, sizeof (server_sockaddr)) == -1)
     312   {
     313      printf("Unable to bind\r\n");
     314      return -1;
     315   }
     316
     317   // Begin listening for clients to connect
     318   if(listen(server_s, 10) == -1)
     319   {
     320      printf("unable to listen");
     321   }
     322
     323   struct timespec delaytm;
     324   delaytm.tv_sec = 0;
     325   delaytm.tv_nsec = 8000000;
     326
     327   // Processing loop
     328   while(1)
     329   {
     330      ServerProcess();
     331
     332      // Small time delay to help OS perform its processing at a smooth rate
     333      nanosleep(&delaytm, NULL);
     334   }
     335
     336   return 0;
    297337}
    298338
     
    307347
    308348
    309 
    310349[[Top]]