Я думаю, что лучше всего читать N
байт, пока чтение не вернет 0 (нет
больше писателей в розетку). Это
правильный?
0 означает EOF, другая сторона закрыла соединение. Если другая сторона связи закрывает соединение, значит это правильно.
Если соединение не закрыто (несколько передач по одному и тому же соединению, болтливый протокол), тогда дело немного сложнее, и поведение обычно зависит от того, есть ли у вас сокет SOCK_STREAM или SOCK_DGRAM.
Сокеты датаграмм уже разграничены для вас ОС.
Потоковые сокеты не разделяют сообщения (все данные являются непрозрачным байтовым потоком), и при желании необходимо реализовать это на уровне приложения: например, путем определения поля размера в структуре заголовка сообщения или использования разделителя (например, '\ n 'для однострочных текстовых сообщений). В первом случае вы должны сначала прочитать заголовок, извлечь длину и, используя длину, прочитать остальную часть сообщения. В другом случае считайте поток в частичный буфер, найдите разделитель и извлеките из буфера сообщение, включая разделитель (вам может потребоваться сохранить частичный буфер, так как в зависимости от протокола можно получить несколько команд с помощью одного recv () / read ( )).
Есть ли способ угадать
размер буфера на который пишется
розетка?
Для потоковых сокетов нет надежного способа, поскольку другая сторона связи все еще находится в процессе записи данных. Представьте себе вполне нормальный случай: размер буфера сокета составляет 32 КБ, а запись 128 КБ. Записывающее приложение блокировало бы внутри send () / write (), ОС ожидала чтения приложением для считывания данных и, таким образом, свободного места для следующего фрагмента записанных данных.
Для сокетов дейтаграмм обычно заранее известен размер сообщения. Или можно попробовать (никогда этого не делал сам) recvmsg (MSG_PEEK) и, если MSG_TRUNC находится в возвращенных msghdr.msg_flags, попытаться увеличить размер буфера.