Thread: Adjust C code to website for queue management ?

  1. #1
    Registered User
    Join Date
    Jul 2019
    Posts
    1

    Question Adjust C code to website for queue management ?

    Hi.
    Some years ago I made telerobots that people remote controlled over the internet.
    I used FOXBOARD
    FOX Board LX832 - Legacy Linux Embedded SBC
    as a server for a webpage and had a file for controlling people to stand in line to log in to my online robots.

    Is it possible to adjust it so that I can use it on a web hotel called
    Support - Wopsa Web Services

    Here is a link to it.
    queue_server.c - Google Drive

    Here is my old code as text.
    ----
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <signal.h>
    
    #define PORT 9034   // port we're listening on
    #define MAX_QUEUE_LEN 3
    
    int main(int argc, char *argv[])
    {
      fd_set master;   // master file descriptor list
      fd_set read_fds; // temp file descriptor list for select()
      struct sockaddr_in myaddr;     // server address
      struct sockaddr_in remoteaddr; // client address
      int fdmax;        // maximum file descriptor number
      int listener;     // listening socket descriptor
      int newfd;        // newly accept()ed socket descriptor
      char buf[256];    // buffer for client data
      char outbuf[256];
      int nbytes;
      int yes=1;        // for setsockopt() SO_REUSEADDR, below
      socklen_t addrlen;
      int i, j;
      int nclients=0;
      struct info {
        struct sockaddr_in in;
        int fd;
        } q_list[MAX_QUEUE_LEN];
    
      FD_ZERO(&master);    // clear the master and temp sets
      FD_ZERO(&read_fds);
    
      // get the listener
      if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
        }
    
      // lose the pesky "address already in use" error message
      if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes,
                                                            sizeof(int)) == -1) {
        perror("setsockopt");
        exit(1);
        }
      // bind
      myaddr.sin_family = AF_INET;
      myaddr.sin_addr.s_addr = INADDR_ANY;
      myaddr.sin_port = htons(PORT);
      memset(myaddr.sin_zero, '\0', sizeof myaddr.sin_zero);
      if (bind(listener, (struct sockaddr *)&myaddr, sizeof(myaddr)) == -1) {
        perror("bind");
        exit(1);
        }
      // listen
      if (listen(listener, 10) == -1) {
        perror("listen");
        exit(1);
        }
     // add the listener to the master set
      FD_SET(listener, &master);
     // keep track of the biggest file descriptor
      fdmax = listener; // so far, it's this one
    
      // main loop
      for(;;) {
        read_fds = master; // copy it
        if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) {
          perror("select");
          exit(1);
          }
        // run through the existing connections looking for data to read
        for(i = 0; i <= fdmax; i++) {
          if (FD_ISSET(i, &read_fds)) { // we got one!!
            if (i == listener) {
              // handle new connections
              addrlen = sizeof(remoteaddr);
              if ((newfd = accept(listener, (struct sockaddr *)&remoteaddr,
                                                               &addrlen)) == -1) { 
                perror("accept"); } else {
                  if (nclients>=MAX_QUEUE_LEN) {
                    sprintf(outbuf,"Queue full (%d connections).\n", nclients);
                    if (send(newfd, outbuf, strlen(outbuf), 0) == -1) {
                      perror("send");
                      }
                    close(newfd); // bye!
                     continue;
                     }
              
                  FD_SET(newfd, &master); // add to master set
                  if (newfd > fdmax) {    // keep track of the maximum
                    fdmax = newfd;
                    }
                  printf("selectserver: new connection from %s on "
                        "socket %d\n", inet_ntoa(remoteaddr.sin_addr), newfd);
                  q_list[nclients].in=remoteaddr;
                  q_list[nclients].fd=newfd;
                  nclients++;
                  printf("now we have %d clients on queue.\n", nclients);  
                  }
              } else { //if data is not from server (listener socket)
                // handle data from a client
                if ((nbytes = recv(i, buf, sizeof(buf), 0)) <= 0) {
                // got error or connection closed by client
                  if (nbytes == 0) {
                  // connection closed
                  printf("selectserver: socket %d hung up\n", i);
                  } else {
                    perror("recv");
                    }
                  close(i); // bye!
                  FD_CLR(i, &master); // remove from master set
                  for(j=0; j<nclients; j++) if (q_list[j].fd == i) break;
                  nclients--;
                  for(; j<nclients; j++)
                    q_list[j]=q_list[j+1];
                    printf("now we have %d clients on queue.\n", nclients);
                    } else { // we got some data from a client
                      if(i == q_list[0].fd)
                      printf("Received = %c\n",buf[0]);
                        else {
                           strcpy(outbuf,"Sorry, you can't send commands. Wait for your turn.\n");
                           if (send(i, outbuf, strlen(outbuf), 0) == -1) {
                             perror("send");
                             }
                           }
                        if(buf[0]=='l') {
                          strcpy(buf,"List of connected clients:\n");
                          if (send(i, buf, strlen(buf), 0) == -1) {
                            perror("send");
                            }
                          for(j = 0; j < nclients; j++) {
                            //if (FD_ISSET(j, &master) && j!= listener) {
                            sprintf(buf,"Client %d: IP %s on socket %d\n", j+1,     inet_ntoa(q_list[j].in.sin_addr), q_list[j].fd );
                            if (send(i, buf, strlen(buf), 0) == -1) {
                              perror("send");
                              }
                            }
                            sprintf(buf,"End of client list.\n");
                            if (send(i, buf, strlen(buf), 0) == -1) {
                              perror("send");
                              }
                            }
                        }
                    }
                }
            }
        }
    
        return 0;
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,666
    The first part is really a question for your chosen web hosting service. Will they allow you to put your own pre-compiled binaries on their platform?

    There are many bugs in your code which would need to be fixed.

    1. All your send() and recv() calls make no account of partial success. In the worst case, you have to deal with both these functions transferring only 1 byte at a time.

    2. You have no mechanism to reduce fdmax as successive connections are closed without new ones being opened.

    3. You would need to handle stdout and stderr differently. Where should they go when you're not around to read them.

    4. Your code formatting needs to be better. It's also begging to be broken down into functions.

    5. Consider how you would restart the server following all those exit(1) calls.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Quote Originally Posted by Salem View Post
    The first part is really a question for your chosen web hosting service. Will they allow you to put your own pre-compiled binaries on their platform?

    There are many bugs in your code which would need to be fixed.

    1. All your send() and recv() calls make no account of partial success. In the worst case, you have to deal with both these functions transferring only 1 byte at a time.

    2. You have no mechanism to reduce fdmax as successive connections are closed without new ones being opened.

    3. You would need to handle stdout and stderr differently. Where should they go when you're not around to read them.

    4. Your code formatting needs to be better. It's also begging to be broken down into functions.

    5. Consider how you would restart the server following all those exit(1) calls.
    6. Filling myaddr.sin_zero with 0's isn't portable. Since you are filling the structure with constant data, you could do:

    Code:
    struct sockaddr_in myaddr = { .sin_family = AF_INET, .sin_port = htons(PORT) };
    IPADDR_ANY is 0. If you want to make sure sin_addr has this value, add .sin_addr.s_addr = IPADDR_ANY (but it's not necessary).
    And delete lines 51 to 54.

    7. You have a listener backlog of 10, but only 3 elements in q_list (why?);

    8. When sending literal strings with send() you could do:

    Code:
    { 
      static const char msg[] = "End of client list.\n";
    
      if ( send( i, msg, sizeof msg - 1, 0 ) == -1 ) 
        ...
    }
    The difference is that you don't need to do a block copy with strcpy()...
    Of course, you should check data was send entirely (but this will fit in a single packet, why bother?

    9. Why are you including signal.h if you don't deal with signals in this code?
    Last edited by flp1969; 07-28-2019 at 04:30 AM.

  4. #4
    null pointer Structure's Avatar
    Join Date
    May 2019
    Posts
    338
    port: WebAssembly

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 1
    Last Post: 05-17-2015, 11:10 AM
  2. Looking for a Code Management System. Advice needed.
    By Kempelen in forum Windows Programming
    Replies: 0
    Last Post: 04-23-2009, 10:06 AM
  3. Code Management Again
    By lchunr in forum C Programming
    Replies: 0
    Last Post: 04-02-2003, 09:58 AM
  4. Code Management
    By GhOsT_DeStRoYeR in forum C Programming
    Replies: 15
    Last Post: 04-01-2003, 11:18 AM

Tags for this Thread