2015-05-10 2 views
1

У меня проблема с печатью с моим сервером. Я хочу, чтобы там была одновременная печать, когда у меня на терминалах два или более клиентов. Тем не менее, я печатаю только один клиент за раз. Как только я закрываю клиента, другие клиенты могут свободно писать на сервер. Что я могу сделать, чтобы исправить мою проблему?UNIX Программирование доменных сокетов в C, проблема с печатью

Я попытался разблокировать раздел печати, который, я думаю, ничего не сделал. (Просто понял, если я это сделаю, то выберите системный вызов трата, я предпочел бы использовать выберите системный вызов) * редактировать

while(TRUE) { 

    FD_ZERO(&readfds); 

    FD_SET(socket1, &readfds); 
    FD_SET(socket2, &readfds); 
    FD_SET(socket3, &readfds); 

    select(socket3+1, &readfds, NULL, NULL, NULL); 

    //add socket1 
    if(FD_ISSET(socket1, &readfds)) { 
     if((client_socket1 = accept(socket1, NULL, NULL)) < 0) { 
      perror("accept1"); 
      exit(EXIT_FAILURE); 
     } 
     printf("New Connection\n"); 

     puts("Welcome message1 sent successfully\n"); 
    } 

    //add socket2 
    if(FD_ISSET(socket2, &readfds)) { 
     if((client_socket2 = accept(socket2, (struct sockaddr *)&addr2, (socklen_t*)&addr2)) < 0) { 
      perror("accept2"); 
      exit(EXIT_FAILURE); 
     } 
     printf("New Connection\n"); 

     puts("Welcome message2 sent successfully\n"); 
    } 

    //add socket 3 
    if(FD_ISSET(socket3, &readfds)) { 
     if((client_socket3 = accept(socket3, (struct sockaddr *)&addr3, (socklen_t*)&addr3)) < 0) { 
      perror("accept3"); 
      exit(EXIT_FAILURE); 
     } 
     printf("New Connection\n"); 

     puts("Welcome message3 sent successfully\n"); 
    } 

    //print from socket 3 
    while((ready = read(client_socket3, buffer, sizeof(buffer))) > 0) { 
     printf("%s\n", buffer); 
    } 

    //print from socket 2 
    while((ready = read(client_socket2, buffer, sizeof(buffer))) > 0) { 
     printf("%s\n", buffer); 
    } 

    //print from socket 1 
    while((ready = read(client_socket1, buffer, sizeof(buffer))) > 0) { 
     printf("%s\n", buffer); 
    } 
} 

ответ

0

Вы должны добавить клиентские сокеты заявления fd_set и select перед тем пытаясь прочитать от них. Кроме того, вы должны сделать все ваши сокеты неблокирующими. В противном случае вызов read будет заблокирован, пока вы не получите данные.

Это быстрое исправление, которое использует recv вместо read для чтения сокетов, но с флагом async MSG_DONTWAIT.

Я не видел нигде, где вы закрывали свои клиентские сокеты или правильно обрабатывали ошибки. Поэтому я вставил некоторый код в качестве подсказки. Кроме того, никогда не рекомендуется «печатать» буфер данных из сокета напрямую. Потому что вы никогда не знаете, завершены ли данные, полученные вами. Всегда удалять нужный буфер после чтения данных из сокета.

Изменить этот блок кода:

//print from socket 3 
while((ready = read(client_socket3, buffer, sizeof(buffer))) > 0) { 
    printf("%s\n", buffer); 
} 

Для этого:

while (1) 
{ 
    int result; 
    result = recv(client_socket3, buffer, sizeof(buffer)-1, MSG_DONTWAIT); 
    if ((result == -1) && 
      ((errno == EAGAIN) || (errno==EWOULDBLOCK))) 
    { 
     // no more data available, but could be available later 
     // use the socket with "select" above to wait for more data 
    } 
    else if ((result == -1) || (result == 0)) 
    { 
     // remote close or unrecoverable error 
     close(client_socket3); 
     client_socket3=-1; 
    } 
    else 
    { 
     // null terminate the buffer before printing 
     buffer[result] = '\0'; 
     printf("%s\n", buffer); 
    } 
} 
+0

Просто интересно, что я изменить все мои в то время как блоки для печати на это? – Michael

+0

@ Майкл - Да. Но почему бы вам не преобразовать вышеприведенный фрагмент кода в автономную функцию, которая принимает сокет в качестве параметра. например 'receive_and_print (socket_t sock) {...}' Тогда вы можете избежать повторения этого блока кода снова и снова. – selbie

Смежные вопросы