Программирование сокетов UNIX в C, выпуск печати

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

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

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);
    }
}

1 ответ

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

Вот быстрое исправление, которое использует recv вместо read читать сокеты, но с асинхронным флагом 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);
    }
}
Другие вопросы по тегам