Как предотвратить фрагментацию пакетов для HttpWebRequest

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

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

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

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

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

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

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

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

4 ответов


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

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


что есть казалось чтобы исправить это, отключает Nagling на ServicePoint, связанной с этим URI, и отправляет запрос как HTTP 1.0 (ни один из них не исправляет его):

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

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

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


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


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

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

http://us.generation-nt.com/answer/too-packets-httpwebrequest-help-23298102.html