2016-06-14 11 views
0

betrachten das nächste Stück Code -Server und mehrere Clients pThreads und wählen Sie()

int get_ready_connection(int s) { 
    /* socket of connection */ 
    int caller; 
    if ((caller = accept(s,NULL,NULL)) < SUCCESS) 
    { 
     server_log->write_to_log(sys_call_error(SERVER, "accept")); 
     return FAILURE; 
    } 

    return caller; 
} 


int establish_connection(sockaddr_in& connection_info) 
{ 
    // Create socket 
    if ((server_sock = socket(AF_INET, SOCK_STREAM, 0)) < SUCCESS) 
    { 
     server_log->write_to_log(sys_call_error(SERVER, "socket")); 
     return FAILURE; 
    } 

    // Bind `sock` with given addresses 
    if (bind(server_sock, (struct sockaddr *) &connection_info, \ 
      sizeof(struct sockaddr_in)) < SUCCESS) 
    { 
     close(server_sock); 
     server_log->write_to_log(sys_call_error(SERVER, "bind")); 
     return FAILURE; 
    } 

    // Max # of queued connects 
    if (listen(server_sock, MAX_PENDING_CONNECTIONS) < SUCCESS) 
    { 
     server_log->write_to_log(sys_call_error(SERVER, "listen")); 
     return FAILURE; 
    } 

    // Create a set of file descriptors and empty it. 
    fd_set set; 
    bool is_inside; 
    int ret_val; 

    while(true) 
    { 
     FD_ZERO(&set); 

     FD_SET(STDIN_FILENO, &set); 
     FD_SET(server_sock, &set); 

     struct timeval tv = {2, 0}; 

     ret_val = select(server_sock + 1, &set, NULL, NULL, &tv); // TODO ret_val 

     is_inside = FD_ISSET(STDIN_FILENO, &set); 
     if(is_inside) 
     { 
      // get user input 
      string user_input; 
      getline(cin, user_input); 

      if ((strcasecmp(user_input.c_str(), EXIT_TEXT) == 0)) 
      { 
       return SUCCESS; 
      } 
     } 

     is_inside = FD_ISSET(server_sock, &set); 
     if(is_inside) 
     { 
      // get the first connection request 
      int current_connection = get_ready_connection(server_sock); 
      if (current_connection == FAILURE) { 
       free_allocated_memory(); 
       exit_write_close(server_log, sys_call_error(SERVER, "accept"), 
           ERROR); 
      } 

      // if exit was not typed by the server's stdin, process the request 
      pthread_t thread; 

      // create thread 
      if (pthread_create(&thread, NULL, command_thread_func, &current_connection) != 0) 
      { 
       free_allocated_memory(); 
       exit_write_close(server_log, sys_call_error(SERVER, "pthread_create"), ERROR); 
      } 
     } 
    } 
} 

Alle im zu tun versuchen, ist zu „hören“ zu STDIN für den Benutzer ‚EXIT‘ in Servers eingeben shell, und darauf warten, dass Clients Befehle von ihren Shells übergeben (jedes Mal, wenn ein Befehl vom Server vom Benutzer empfangen wird, analysiert der Server ihn, und der Server erstellt einen Thread, der die Ausführung des Befehls abwickelt) Um es simultan zu tun Ich habe select() benutzt.

Wenn ich mit einem einzigen Thread arbeite, ist alles perfekt. Aber das Problem ist, wenn ich einen anderen Klienten verbinde, bekomme ich einen Segeld Fehler. Ich vermute, dass das Problem hier liegt. irgendwelche Vorschläge?

+0

Dies ist ohne den Code 'command_thread_func' nicht zu verantworten. Außerdem [bitte ein MCVE angeben] (http://stackoverflow.com/help/mcve). –

+1

Ich schlage vor, dass Sie Ihr Programm in einem Debugger ausführen, und wenn es abstürzt, sagen Sie dem Debugger, einen Stack-Trace zu drucken, der die genaue Zeile zeigt, wo der Absturz aufgetreten ist. Das wird sehr hilfreich sein, um herauszufinden, warum der Unfall passiert ist. –

Antwort

1

schwer zu wissen, ob dies Ihr genaues Problem ist, aber das ist definitiv ein Problem:

Sie nicht pthread_create anrufen und einen Zeiger auf eine Stapelgröße (&current_connection) als Thread-Funktion Argument liefern. Zum einen unterliegt es sofortiger Zerstörung, sobald der Elternteil diesen Geltungsbereich verlässt.

Zweitens wird es beim nächsten Anruf auf get_ready_connection überschrieben werden.