Получение количества байтов, доступных для чтения в сокете - PullRequest
2 голосов
/ 02 февраля 2012

Вот мой сценарий.У меня есть TCP-клиент, который разговаривает с сервером.Сервер и клиент работают на локальном компьютере (Windows).

Диалоговое окно выглядит примерно так:

  1. Клиент отправляет данные на сервер (Запрос)
  2. Клиент отключается для отправки по сокету
  3. Клиент блокирует запрос на чтение через ответ
  4. Сервер получает данные, обрабатывает и отправляет ответ (один кадр, не разбитый на куски)
  5. Сервер отключается для отправки по сокету
  6. Клиент получает ответ и продолжает обработку.

На шаге 3 я использую вызов recv () дляблокировать и читать данные из сокета.На данный момент, я хотел бы посмотреть, сколько байтов данных доступно, чтобы я мог выделить столько памяти.Изначально известно, что сервер отправил все данные, и для этого запроса больше нет данных.(См. Шаг 5 выше).

Я пробовал recv () с опцией MSG_PEEK, но, похоже, общее количество доступных байтов не выдается.

Есть ли способ получить его?

Заранее спасибо.

Ответы [ 4 ]

3 голосов
/ 14 ноября 2012

Один из способов сделать это, без предварительного выделения или перераспределения буферов, состоит в следующем: (a) отправить количество байтов, которые отправляет отправитель (например, как четыре байта int, в порядке сетевых байтов), (b ) пусть получатель получит эти четыре байта и выделит буфер приема, а затем (с) получит, чтобы получатель отправил фактические данные ранее отправленной длины. Обратите внимание, что (c) может произойти отправитель без получения обратной связи или ответа относительно (a) от получателя.

Я пытался использовать fstat для получения объема данных, доступных в сокете, но он не выглядит переносимым. В системе Mac это работает для моего приложения. В системе Linux это не так.

2 голосов
/ 02 февраля 2012

Используя TCP, невозможно узнать, сколько там байтов.Помните, что TCP - это «потоковый» протокол, поток запускается, но не заканчивается до тех пор, пока соединение не будет закрыто.

Что вы можете сделать, это прочитать маленькие порции в буфер и увеличить его,необходимо.

1 голос
/ 03 февраля 2012

По крайней мере, в Windows вы можете использовать ioctlsocket() с командой FIONREAD, чтобы определить текущее число байтов, доступных для recv() для чтения без блокировки.К тому времени, когда вы на самом деле вызываете recv(), возможно, поступило больше байтов.

Как сказал @LokiAstari, вы должны вызывать recv() в цикле, пока он не вернет 0 байтов, чтобы указать, что сокетзакрыто.Вам не нужно знать, сколько байтов доступно, просто передавайте буфер фиксированной длины каждый раз, и recv() вернет, сколько байтов было фактически прочитано.Добавьте каждое чтение буфера ненулевой длины в другой буфер, который увеличивается по мере необходимости, пока вы не получите все данные, а затем обработайте этот второй буфер, когда будете готовы.

0 голосов
/ 23 мая 2013

Это частично зависит от размера ответа, потому что даже если отправить его как один чанк, базовый транспорт может разбить его на чанки.Например, Ethernet имеет максимальный размер пакета 1500 байтов.Хотя вы отправляете все это один раз, хотя вполне вероятно, что вы получите все сразу, это не гарантируется, если вы используете TCP, потому что он ориентирован на поток.У вас гораздо больше шансов получить ответ в виде одного пакета, если вы используете UDP.

...