Зная, когда прекратить чтение из сокета .NET на уровне HTTP - PullRequest
1 голос
/ 24 февраля 2011

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

Мой вопрос - по какому принципу работают библиотеки более высокого уровня (например,HTTP-уровень WebRequest) использовать для того, чтобы остановить чтение из сокета и представить клиенту полное сообщение, не прибегая к каким-либо тайм-аутам чтения?Похоже, что протокол HTTP не предлагает никаких токенов "EOF" ...

Ответы [ 3 ]

3 голосов
/ 24 февраля 2011

HTTP 1.1 управляет этим с помощью одного из двух механизмов. Либо в заголовках отправляется content-length , либо используется кодированная передача chunked . Кодирование в виде фрагментированной передачи является одним из больших преимуществ HTTP 1.1 по сравнению с HTTP 1.0, где в случае отсутствия длины контента невозможно окончательно определить конец передачи, что приводит к несоответствию между проблемами передачи и фактическим окончанием полезной нагрузки. , В некоторых случаях (например, аудиопотоки по HTTP) отсутствует длина контента или другое кодирование, которое могло бы указывать на окончание передачи, но в этом случае это не будет иметь большого значения для клиента.

1 голос
/ 24 февраля 2011

Есть несколько способов проверить, ожидают ли сокеты данных. Один из них - просто проверить свойство Pending каждого сокета и вызывать метод Receive только при наличии данных. Однако это не очень хорошо масштабируется, и я бы рекомендовал использовать его только в приложениях с одним подключением или около того.

Функция Socket.Select может принимать IList of Sockets и через короткий промежуток времени сократит этот список до тех сокетов, которые ожидают данных. После этого вы можете безопасно получать звонки на них без блокировки.

Другой способ, который является предпочтительным, заключается в использовании API асинхронного сокета. (Звоните на BeginReceive или BeginRead в NetworkStream). В этих случаях вызов не будет блокироваться, и вы можете продолжить выполнение кода после вызова. Вы передаете функцию в качестве аргумента, который должен выполняться при ожидании данных в сокете. Это обрабатывается в фоновом потоке в пуле потоков .NET, поэтому здесь возникают проблемы с параллелизмом, в отличие от двух предыдущих методов. Асинхронные операции выполняются на гораздо более низком уровне в ОС, используя прерывания, чтобы сообщить ЦПУ, когда данные ожидают в сети, вместо того, чтобы периодически запрашивать данные, как это делает Select.

0 голосов
/ 24 февраля 2011

В HTTP, content-length Заголовок HTTP определяет, когда сокет может быть закрыт.

В TCP это произвольно, и обычно клиент или сервер отправляет специальное сообщение, чтобы уведомить, что соединение разрывается.

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