Как предотвратить фрагментацию пакета для HttpWebRequest - PullRequest
7 голосов
/ 05 февраля 2010

У меня проблема с использованием HttpWebRequest против HTTP-демона на встроенном устройстве. Кажется, проблема в том, что между записью заголовков http в поток сокета и полезной нагрузкой http (POST) достаточно задержки, чтобы сокет высвобождал содержимое буфера сокета на сервер. Это приводит к тому, что HTTP-запрос разделяется на два пакета (фрагментация).

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

Похоже, что в HttpWebRequest отсутствуют какие-либо свойства, обеспечивающие этот уровень контроля над сокетом, используемым для отправки, и невозможно получить доступ к самому сокету (то есть с помощью отражения), поскольку он создается только во время отправить, а затем освободить (как часть пула исходящих http-соединений). Свойство BufferWriteStream просто буферизует содержимое тела в веб-запросе (таким образом, оно все еще доступно для перенаправлений и т. Д.) И, по-видимому, не влияет на способ записи всего запроса в сокет.

Так что же делать?

(я действительно стараюсь не переписывать HTTP-клиент из сокета вверх)

Одним из вариантов может быть написание какого-то прокси-сервера, которому HttpWebRequest отправляет (возможно, через ServicePoint), и в этой реализации буферизует весь TCP-запрос. Но это похоже на тяжелую работу.

Он также отлично работает, когда я запускаю Fidder (по той же причине), но это не совсем вариант в нашей производственной среде ...

[ps: я знаю, что именно интервал между фрагментированными пакетами является проблемой, потому что я запустил тест на уровне сокетов, где я явно управлял фрагментацией, используя сокет NoDelay]

Ответы [ 4 ]

2 голосов
/ 24 марта 2011

В конце концов поставщик выполнил обновление прошивки, включающее новую версию HTTPD, и проблема исчезла. Они использовали BusyBox Linux, и, очевидно, была другая проблема с реализацией HTTPD, от которой они пострадали.

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

1 голос
/ 08 февраля 2010

То, что , по-видимому, исправило, отключает Nagling в ServicePoint, связанном с этим URI, и отправляет запрос как HTTP 1.0 (ни один из них, похоже, не исправляет):

var servicePoint = ServicePointManager.FindServicePoint(uri.Uri);
servicePoint.UseNagleAlgorithm = false;

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

Интересно, как сложно написать дефрагментирующий прокси ...

0 голосов
/ 13 ноября 2012

Просто глядя на проблему разделения пакетов на стороне клиента, я отправил ответ на свой вопрос, связанный с этим:

Я видел ответ здесь:

http://us.generation -nt.com / ответ / слишком-пакеты-HttpWebRequest-помощь-23298102.html

0 голосов
/ 05 февраля 2010

Является ли ваш встроенный сервер сервером HTTP / 1.1? Если это так, попробуйте установить Expect100Continue = false в веб-запросе, прежде чем вызывать GetRequestStream (). Это гарантирует, что стек HTTP не ожидает ответа заголовка «HTTP / 1.1 100 continue» от сервера перед отправкой тела объекта. Таким образом, даже если пакеты все еще будут разделены между заголовком и телом, межпакетный интервал будет меньше.

...