Advertisement
Guest User

Untitled

a guest
Jul 14th, 2016
294
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.26 KB | None | 0 0
  1. /*
  2. ** selectserver.c -- a cheezy multiperson chat server
  3. */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <unistd.h>
  9. #include <sys/types.h>
  10. #include <sys/socket.h>
  11. #include <netinet/in.h>
  12. #include <arpa/inet.h>
  13. #include <netdb.h>
  14.  
  15. #define PORT "1234"   // port we're listening on
  16.  
  17. // get sockaddr, IPv4 or IPv6:
  18. void *get_in_addr(struct sockaddr *sa)
  19. {
  20.     if (sa->sa_family == AF_INET) {
  21.         return &(((struct sockaddr_in*)sa)->sin_addr);
  22.     }
  23.  
  24.     return &(((struct sockaddr_in6*)sa)->sin6_addr);
  25. }
  26.  
  27. int main(void)
  28. {
  29.     printf("lol");
  30.     fd_set master;    // master file descriptor list
  31.     fd_set read_fds;  // temp file descriptor list for select()
  32.     int fdmax;        // maximum file descriptor number
  33.  
  34.     int listener;     // listening socket descriptor
  35.     int newfd;        // newly accept()ed socket descriptor
  36.     struct sockaddr_storage remoteaddr; // client address
  37.     socklen_t addrlen;
  38.  
  39.     char buf[256];    // buffer for client data
  40.     int nbytes;
  41.  
  42.     char remoteIP[INET6_ADDRSTRLEN];
  43.  
  44.     int yes = 1;        // for setsockopt() SO_REUSEADDR, below
  45.     int i, j, rv;
  46.  
  47.     struct addrinfo hints, *ai, *p;
  48.  
  49.     FD_ZERO(&master);    // clear the master and temp sets
  50.     FD_ZERO(&read_fds);
  51.  
  52.     // get us a socket and bind it
  53.     memset(&hints, 0, sizeof hints);
  54.     hints.ai_family = AF_UNSPEC;
  55.     hints.ai_socktype = SOCK_STREAM;
  56.     hints.ai_flags = AI_PASSIVE;
  57.     if ((rv = getaddrinfo(NULL, PORT, &hints, &ai)) != 0) {
  58.         fprintf(stderr, "selectserver: %s\n", gai_strerror(rv));
  59.         exit(1);
  60.     }
  61.  
  62.     for (p = ai; p != NULL; p = p->ai_next) {
  63.         listener = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
  64.         if (listener < 0) {
  65.             continue;
  66.         }
  67.  
  68.         // lose the pesky "address already in use" error message
  69.         setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
  70.  
  71.         if (bind(listener, p->ai_addr, p->ai_addrlen) < 0) {
  72.             close(listener);
  73.             continue;
  74.         }
  75.  
  76.         break;
  77.     }
  78.  
  79.     // if we got here, it means we didn't get bound
  80.     if (p == NULL) {
  81.         fprintf(stderr, "selectserver: failed to bind\n");
  82.         exit(2);
  83.     }
  84.  
  85.     freeaddrinfo(ai); // all done with this
  86.  
  87.                       // listen
  88.     if (listen(listener, 10) == -1) {
  89.         perror("listen");
  90.         exit(3);
  91.     }
  92.  
  93.     // add the listener to the master set
  94.     FD_SET(listener, &master);
  95.  
  96.     // keep track of the biggest file descriptor
  97.     fdmax = listener; // so far, it's this one
  98.  
  99.                       // main loop
  100.     printf("server started");
  101.     for (;;) {
  102.         read_fds = master; // copy it
  103.         if (select(fdmax + 1, &read_fds, NULL, NULL, NULL) == -1) {
  104.             perror("select");
  105.             exit(4);
  106.         }
  107.  
  108.         // run through the existing connections looking for data to read
  109.         for (i = 0; i <= fdmax; i++) {
  110.             if (FD_ISSET(i, &read_fds)) { // we got one!!
  111.                 if (i == listener) {
  112.                     // handle new connections
  113.                     addrlen = sizeof remoteaddr;
  114.                     newfd = accept(listener,
  115.                         (struct sockaddr *)&remoteaddr,
  116.                         &addrlen);
  117.  
  118.                     if (newfd == -1) {
  119.                         perror("accept");
  120.                     }
  121.                     else {
  122.                         FD_SET(newfd, &master); // add to master set
  123.                         if (newfd > fdmax) {    // keep track of the max
  124.                             fdmax = newfd;
  125.                         }
  126.                         printf("selectserver: new connection from %s on "
  127.                             "socket %d\n",
  128.                             inet_ntop(remoteaddr.ss_family,
  129.                                 get_in_addr((struct sockaddr*)&remoteaddr),
  130.                                 remoteIP, INET6_ADDRSTRLEN),
  131.                             newfd);
  132.                     }
  133.                 }
  134.                 else {
  135.                     // handle data from a client
  136.                     if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
  137.                         // got error or connection closed by client
  138.                         if (nbytes == 0) {
  139.                             // connection closed
  140.                             printf("selectserver: socket %d hung up\n", i);
  141.                             perror("hung up");
  142.                         }
  143.                         else {
  144.                             perror("recv");
  145.                         }
  146.                         close(i); // bye!
  147.                         FD_CLR(i, &master); // remove from master set
  148.                     }
  149.                     else {
  150.                         // we got some data from a client
  151.                         for (j = 0; j <= fdmax; j++) {
  152.                             // send to everyone!
  153.                             if (FD_ISSET(j, &master)) {
  154.                                 // except the listener and ourselves
  155.                                 if (j != listener && j != i) {
  156.                                     if (send(j, buf, nbytes, 0) == -1) {
  157.                                         perror("send");
  158.                                     }
  159.                                 }
  160.                             }
  161.                         }
  162.                     }
  163.                 } // END handle data from client
  164.             } // END got new incoming connection
  165.         } // END looping through file descriptors
  166.     } // END for(;;)--and you thought it would never end!
  167.  
  168.     return 0;
  169. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement