2012-04-09 3 views
0

Ich habe eine Aufgabe, ein Serverprogramm zu schreiben, das mehrere Clients akzeptiert. Ich schreibe in C Sprache und versuche dies mit einer select() Anweisung zu erreichen. Ich bin in der Lage zu kompilieren, aber wenn ich Telnet in, bekomme ich eine "Socket-Operation auf Nicht-Socket-Fehler." Ich habe versucht, den Fehler zu erforschen, kann aber nichts zu hilfreich finden. Jede Hilfe wäre willkommen.C lang, Multi-Client Server, Fehler: Socket-Operation auf Nicht-Socket

Der Ausgang meines Servers ist:

$ ./assign2 33333 
Waiting for connection... 
fd is 0 
EchoServ recv error: Socket operation on non-socket 
fd is 1 
EchoServ recv error: Socket operation on non-socket 
EchoServ recv error: Socket operation on non-socket 

Der Ausgang des Telnet ist:

$ telnet localhost 33333 
Trying 127.0.0.1... 
Connected to localhost.localdomain (127.0.0.1). 
Escape character is '^]'. 
Welcome to EchoServ chat. 

Mein Server-Code:

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 
#include <string.h> 
#include <stdlib.h> 
#include <unistd.h> 

#define PORT 50000 

main(int argc, char *argv[]) 
{ 
    char    buf[ BUFSIZ ], /* buffer for incoming data */ 
         *endptr, /* for strtol() */ 
         *message = "Welcome to EchoServ chat. \r\n"; /* welcome message */ 
    int     masterSocket, /* main listening socket for server */ 
         newSocket, /* new sockets for connecting clients */ 
         opt = 1, /* for port reuse code */ 
         nBytes, /* # of incoming bytes */ 
         addrlen; 
    int     i,j; /* temp vars */ 
    short int   port; /* port number */ 
    fd_set    master; /* master file descriptor list */ 
    fd_set    temp_fds; /* temp file descriptor list for select() */ 
    int     fdmax; /* maximum file descriptor number */ 
    struct sockaddr_in sin; 

    /* Get port number from the command line, or 
     set to default port if no arguments were supplied */ 
    if (argc == 2) { 
     port = strtol(argv[1], &endptr, 0); 
     if (*endptr) { 
      fprintf(stderr, "EchoServ: Invalid port number.\n"); 
      exit(EXIT_FAILURE); 
     } 
    } 
    else { 
     port = PORT; 
    } 

    FD_ZERO(&master); /* clear the master and temp sets */ 
    FD_ZERO(&temp_fds); 

    /* Get an internet domain socket */ 
    if ((masterSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 
     perror("EchoServ socket error"); 
     exit(1); 
    } 

    /* Complete the socket structure */ 
    memset(&sin, 0, sizeof(sin)); 
    sin.sin_family = AF_INET; 
    sin.sin_addr.s_addr = INADDR_ANY; 
    sin.sin_port = htons(port); 

    /* Bind the socket to the port number */ 
    if (bind(masterSocket, (struct sockaddr *) &sin, sizeof(sin)) == -1) { 
     perror("EchoServ bind failed"); 
     exit(1); 
    } 

    /* Allow port reuse */ 
    if (setsockopt(masterSocket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) { 
     perror("EchoServ setsockopt error"); 
     exit(1); 
    } 

    /* Listen for clients that want to connect.   */ 
    if (listen(masterSocket, 5) == -1) { 
     perror("EchoServ listen error"); 
     exit(1); 
    } 

    /* add masterSocket to the master set */ 
    FD_SET(masterSocket, &master); 

    /* track largest file descriptor, starting with masterSocket */ 
    fdmax = masterSocket; 


    /* Wait for a client connection, then accept it. */ 

    puts ("Waiting for connection..."); 
    while(1){ 
     temp_fds = master; /* copy master set to temp set */ 
     //addrlen = sizeof(sin); 
     /* wait for activity on a socket */ 
     if (select(fdmax+1, &temp_fds, NULL, NULL, NULL) == -1) { 
      perror("EchoServ select error"); 
      exit(1); 
     } 

     for (i = 0; i <= fdmax; i++){ 
      printf("fd is %d\n", i); /*debug*/ 
      if (FD_ISSET(i, &temp_fds)){ /* true if file descriptor is in set */ 

       /* accept new connection */    
       if (i == masterSocket){ 
        addrlen = sizeof(sin); 
        if ((newSocket = accept(masterSocket, (struct sockaddr *) &sin, &addrlen)) == -1) 
         perror("EchoServ: accept error"); 
        else { 
         printf("New connection accepted\n"); /*debug*/ 
         FD_SET(newSocket, &master); /* add new connection to master set */ 
         if (newSocket > fdmax) /* update max descriptor */ 
          fdmax = newSocket; 
         //print details of new connection 
         printf("New connection on %s:%d, socket fd is %d \n", 
         inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), newSocket); 

         //send new connection greeting message 
         if(send(newSocket, message, strlen(message), 0) == -1) 
         { 
          perror("EchoServ welcome message error"); 
         } 
         puts("Welcome message sent successfully"); 
        } 
       } 
      } 

      /* handle incoming data */ 
      else{ 
       if ((nBytes = recv(i, buf, sizeof(buf), 0)) <= 0){ /* error or closed connection */ 
        if (nBytes == 0) /* connection closed */ 
         printf("EchoServ: socket %d closed by client\n", i); 
        else /* recv error */ 
         perror("EchoServ recv error"); 
        close(i); /* close socket */ 
        FD_CLR(i, &master); /* remove from master set */ 
       } 
       else { /* got some data */ 
        for(j = 0; j <= fdmax; j++){ 
         if (FD_ISSET(j, &master)){ /* send data to all sockets */ 
          if(j != i && j != masterSocket){ /* except self and masterSocket */ 
           if (send(j, buf, nBytes, 0) == -1) 
            perror("EchoServ send error"); 
          } 
         } 
        } 
       } 
      } 
     } 
    } 

    return(0); 
} 

Danke für die Hilfe.

+0

Ich bin gespannt: Woher hast du diesen Code-Stil? – cnicutar

Antwort

0

So testen Sie if (FD_ISSET(i, &temp_fds)) und auf die else-Zweig Sie versuchen, recv auf i. Sie versuchen also nur zu empfangen, wenn i ungültig ist oder blockieren würde.

Dies alles stammt natürlich aus der unbegrenzten Verwendung von Blöcken und Klammern. Du hast wahrscheinlich gemeint, dass sonst mit if (i == masterSocket) gepaart werden soll.

+0

Sie haben Recht. Ich hatte das sonst mit dem falschen verbunden. Zu viele Klammern: P Jetzt kann ich eine Verbindung herstellen, aber die Daten werden nicht zwischen Clients übertragen. – rennX

+0

Herausgefunden, warum Daten nicht übergeben wurden. Ich war kurz eine Menge von Eltern auf: if ((nBytes = recv (i, buf, sizeof (buf), 0)) <= 0) – rennX