Чтение сообщения из сокета в C

Я пытаюсь понять чтение из сокета в C (под Linux), это только часть кода:

while(success == 0) {

    while((n = read(sockfd, buffer, BUFFSIZE, 0)) > 0) {
        printf("%s",buffer);
        bzero(buffer,BUFFSIZE);
    }
    success = 1;
    printf("###");

}

сообщение печатается, но три хэша (###) никогда не печатаются? Почему? Программа, похоже, блокируется на read (). Здесь я просто печатаю, но мне нужно сделать буфер всего сообщения, а затем обработать его.

6 ответов


программа другой конец сокета нет закрытие, ни закрытие свои пишет (которые ваши читает), поэтому ваш конец не знает, что все закончено - действительно, логически это не закончено, пока другой конец не скажет, что вам больше нечего читать.

Как правило, ваша логика уровня приложения должна знать заранее, сколько читать, или читает, пока не будет получен определенный Терминатор, или другой конец изящно закрывает или выключает розетку.

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


вам нужно знать, насколько велико сообщение, которое вы получаете, и продолжайте читать, пока у вас не будет всего сообщения (чтение может вернуть только часть Вашего сообщения).

do {
    nread = read(s, buf, to_read);
    if (nread < 0 && errno == EINTR)
            continue;
    if (nread < 0) {
            perror("read");
            exit(1);
    }

    if (nread == 0) {
            printf("socket closed");
            ... do something appropiate ...
            ... (reconnecting/exiting the loop with an error/...) ...
    }

    to_read -= nread;
    buf += nread;
} while (to_read > 0); 

to_read - длина в байтах, которую вы ожидаете прочитать. buf имеет достаточно места для него. После каждого чтения обновите to_read и buf соответственно. И, конечно, с ошибками нужно обращаться правильно.


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

ief2


попробуйте добавить \n. Иногда неоконченные строки не печатаются.

EDIT: о, подождите, вы имеете в виду, что программа не заканчивается?


Я думаю, ваш цикл while никогда не заканчивается, потому что чтение либо успешно, либо блокирует.


ваш цикл while закончится только тогда, когда n имеет значение ноль.

когда бы вы ожидали читать чтобы вернуть нулевое значение? Удовлетворяют ли данные, которые вы отправляете в этот сокет, какому-либо условию, которое привело бы к возвращению нуля?