Проблема чтения сокетов в Unix на C - PullRequest
0 голосов
/ 17 января 2012

Я использую C для реализации клиент-серверного приложения.Клиент отправляет информацию на сервер, а сервер использует ее для отправки информации обратно.В настоящее время я нахожусь в процессе написания кода для обработки получения данных, чтобы гарантировать, что все они фактически получены.

Проблема, с которой я столкнулся, лучше всего объяснить после показа некоторого кода:

int totalRead = 0;
char *pos = pBuffer;
while(totalRead < 6){
if(int byteCount = read(hSocket, pos, BUFFER_SIZE - (pos-pBuffer)>0)){
    printf("Read %d bytes from client\n", byteCount);
    pos += byteCount;
    totalRead += byteCount;
    }else return -1;
}

Приведенный выше код выполняется на стороне сервера и 6 раз выведет «Read 1 bytes from client», и программа продолжит работать нормально.Я жестко запрограммировал 6 здесь, зная, что я пишу 6 байтов со стороны клиента, но я заставлю свой протокол требовать, чтобы первый отправленный байт был длиной остальной части буфера.

int byteCount = read(hSocket, pBuffer, BUFFER_SIZE);
printf("Read %d bytes from client", byteCount);

Приведенный выше код, используемый вместо первого сегмента кода, напечатает «Чтение 6 байтов из клиента» и продолжит работать нормально, но это не гарантирует, что я получил каждый байт, если, например, было прочитано только 5.

Может кто-нибудь объяснить мне, почему это происходит и возможное решение?Я предполагаю, что первый метод обеспечивает доставку всех байтов, но кажется неэффективным чтение одного байта за раз ...

О, и это происходит в разветвленном дочернем процессе, и я использую tcp / ip.

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

Ответы [ 2 ]

6 голосов
/ 17 января 2012

По сути, правильный способ сделать это - гибрид ваших двух фрагментов кода. Сделайте первый, но не просто читайте по одному байту за раз; попросите все байты, которые вы ожидаете. Но посмотрите на bytesRead, и, если оно меньше, чем вы ожидали, отрегулируйте указатель получателя, откорректируйте ожидаемый номер и снова наберите read(). Вот как это работает: иногда ожидаемые данные распределяются по пакетам и не все доступны одновременно.

Читая ваш комментарий ниже и просматривая ваш код, я был озадачен, потому что да, именно это вы пытаетесь сделать. Но потом я очень внимательно посмотрел на твой код:

read(hSocket, pos, BUFFER_SIZE - (pos-pBuffer)>0)){
                                              ^
                                              |
                                THIS ---------|

То, что "> 0" это внутри в скобках, содержащих аргументы чтения, а не снаружи; это означает, что это часть аргументов! Фактически, ваш последний аргумент интерпретируется как

(BUFFER_SIZE - (pos-pBuffer)) > 0

который равен 1, до конца, когда он становится 0.

0 голосов
/ 17 января 2012

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

Если вы получили отрицательный результат из read или write, вы получили ошибку.Ноль указывает, что передача завершена (больше не было байтов для отправки), а любое число выше нуля указывает, сколько байтов было отправлено в последнем вызове на read или write соответственно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...