2017-03-05 5 views
0

In meiner Hauptfunktion habe ich (unter Verwendung von Lernprogrammen usw.) einen iterativen Server erstellt, der einfach eine Nachricht empfängt und sie an den Client zurückgibt. Allerdings übergebe ich FD_SETSIZE in die select() - Funktion, die den Dateideskriptor tatsächlich nicht um 1 vom Maximum inkrementiert.Wie kann ich diesen iterativen Server ändern, um den höchsten Dateideskriptor zu erhalten?

#include <dns_sd.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <stdlib.h> 
#include <time.h> 
#include <math.h> 

#include <string.h> 
#include <errno.h> 
#include <time.h> 
#include <math.h> 

#include <sys/select.h>  /* <===== */ 


#ifdef _WIN32 
#include <process.h> 
typedef int pid_t; 
#define getpid _getpid 
#define strcasecmp _stricmp 
#define snprintf _snprintf 
#else 
#include <sys/time.h>  // For struct timeval 
#include <unistd.h>   // For getopt() and optind 
#include <arpa/inet.h>  // For inet_addr() 
#endif 

#include <netdb.h> 
#include <sys/select.h> 
#include <fcntl.h> 
#include <err.h> 

#define BUFFER_SIZE 1024 
#define MAX_CLIENTS 100  /* <===== */ 


// ... lots of skipped code here 


/** 
* Creates a connection with a socket. It handles 
* socket(), bind(). 
* 
* @name create_socket 
* @param server_addr the server address 
* 
*/ 

int create_socket(struct sockaddr_in* server) { 

    /* Create the listener socket as TCP socket */ 

    int sock = socket(PF_INET, SOCK_STREAM, 0); //use protocol family, internet 

    if (sock < 0) { 
     perror("socket()"); 
     exit(EXIT_FAILURE); 
    } 


    bzero(&*server, sizeof(*server)); // causing segault 
    //server->sin_family = PF_INET; 
    server->sin_family = AF_INET; 
    //server->sin_addr.s_addr = INADDR_ANY; 
    server->sin_addr.s_addr = htonl(INADDR_ANY); 

    unsigned short port = 8129; 
    server->sin_port = htons(port); //the port is chosen as the first available. 

    int len = sizeof(*server); 

    if (bind(sock, (struct sockaddr*) &*server, len) < 0) { 
     perror("bind()"); 
     exit(EXIT_FAILURE); 
    } 

    return sock; 
} 

Hier ist die Hauptfunktion:

/** MAIN **/ 

int main() 
{ 

    /* Socket Structures */ 
    struct sockaddr_in server, client, temp; 
    fd_set readfds; 
    int client_sockets[ MAX_CLIENTS ]; /* client socket fd list */ 
    int client_socket_index = 0; /* next free spot */ 


    /* Create the listener socket as TCP socket */ 
    int sock = create_socket(&server); 

    listen(sock, 5); /* 5 is number of waiting clients */ 
    //printf("Listener bound to port %d\n", port); 

    printf("Started server; listening on port: %d\n", local_port); 

    /** Read from and Write to the Client **/ 

    int fromlen = sizeof(client); 

    char buffer[ BUFFER_SIZE ]; 

    int i; 

    while (1) 
    { 
#if 1 
     struct timeval timeout; 
     timeout.tv_sec = 3; 
     timeout.tv_usec = 500; /* 3 AND 500 microseconds */ 
#endif 

     FD_ZERO(&readfds); 
     FD_SET(sock, &readfds); // FD_SET to include listener fd, sock 

     for (i = 0 ; i < client_socket_index ; i++) 
     { 
      FD_SET(client_sockets[ i ], &readfds); //Set FD_SET to include client socket fd 
     } 

#if 0 
     /* BLOCK */ 
     int ready = select(FD_SETSIZE, &readfds, NULL, NULL, NULL); 
     /* ready is the number of ready file descriptors */ 
     printf("select() identified %d descriptor(s) with activity\n", ready); 
#endif 

#if 1 
     int ready = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout); 
     if (ready == 0) { 
     //printf("No activity\n"); 
      continue; 
     } 
#endif 

     if (FD_ISSET(sock, &readfds)) 
     { 
      int newsock = accept(sock, 
        (struct sockaddr *)&client, 
        (socklen_t *)&fromlen); 
      /* this accept() call we know will not block */ 
      printf("Accepted client connection\n"); 
      client_sockets[ client_socket_index++ ] = newsock; 
     } 

     for (i = 0 ; i < client_socket_index ; i++) 
     { 
      int fd = client_sockets[ i ]; 

      if (FD_ISSET(fd, &readfds)) 
      { 
       int n, guess, success; 

       /** Recieve user input, check for errors **/ 
       n = recv(fd, buffer, BUFFER_SIZE - 1, 0); 

       if (n < 0) 
       { 
        perror("recv()"); 
       } 
       else if (n == 0) 
       { 
        int k; 
        printf("Client on fd %d closed connection\n", fd); 
        close(fd); 
        /* remove fd from client_sockets[] array: */ 
        for (k = 0 ; k < client_socket_index ; k++) 
        { 
         if (fd == client_sockets[ k ]) 
         { 
          /* found it -- copy remaining elements over fd */ 
          int m; 
          for (m = k ; m < client_socket_index - 1 ; m++) 
          { 
           client_sockets[ m ] = client_sockets[ m + 1 ]; 
          } 
          client_socket_index--; 
          break; /* all done */ 
         } 
        } 

       } else { 

        buffer[n] = '\0'; 

        printf("Recieved %s",buffer); 

        n = send(fd, buffer, strlen(buffer), 0); 

        /* Divide input into parts and get the guess */ 


       } 
      } 
     } 
    } 

    return EXIT_SUCCESS; /* we never get here */ 
} 

Antwort

0

Noch ein paar Stunden googeln und ich es herausgefunden! Sehr kleine Änderung.

while(1) { 
//... 
    int maxfd = sock; 

    for (i = 0; i < client_socket_index ; i++) 
    { 
     int sd = client_sockets[i]; 
     FD_SET(sd, &readfds); //Set FD_SET to include client socket fd 
     if(sd > maxfd) 
      maxfd = sd; 
    } 

    int ready = select(maxfd+1, &readfds, NULL, NULL, &timeout); 

} 
Verwandte Themen