4

I have a problem whereby I have lots of very small web service calls to a Java endpoint (hosted on Oracle GlassFish 3.1.X). I added this service as a Service Reference (using the remote wsdl file) and use a BasicHttpBinding to reach it.

Since the service is located half the world away plus going across the internet, we frequently experience some packet loss when reaching the destination. We are looking at any way possible to reduce the impact of these occurrences. We have been using Wireshark to give us detailed knowledge of what is going across the wire to our destination, and back again. I was curious to see that for every single request we generate, we are sending 2 packets. The packet boundary is always between the HTTP header and the <s:Envelope> tag. To me this is a big overhead, particularly in my environment where I want to minimise the amount of packets sent (to reduce overall packetloss).

In most cases (99% of our calls), the HTTP header packet is 210 bytes followed by a SOAP envelope packet of 291 bytes (excluding the 54 bytes of TCP/IP overhead for each packet). Totalling these gives 501 bytes - just over a third of our Max Segment Size of 1460 bytes. Why isn't WCF sending this HTTP POST request as a single packet of 501 bytes (555 bytes if you include the 54 bytes of TCP/IP overhead)?

Wireshark reassembly screenshot

Does anyone know why it does this? It almost seems as if the HttpWebRequest object is calling .Flush() on the stream after writing it's headers but I'm not sure why it would do this?

I've tried different combinations on these:

ServicePointManager.UseNagleAlgorithm = false;
ServicePointManager.Expect100Continue = false;

With no effect.

EDIT

Wrong: I've investigated a bit further and when a HttpWebRequest.GetRequestStream() is called, it does write the headers to the stream immediately. At some stage before you write to the Stream that is given back to you, the network would Flush these (I guess? Unless a deliberate flush is happening somewhere). When you finally start writing to the stream, it has already sent the header packet. Not sure how to prevent this, it seems a very hard assertion inside the HttpWebRequest code that called GetRequestStream() will write the headers. For my small requests, I want nothing to be written until I have closed the stream but that goes against the streaming nature of it.

jamespconnor
  • 1,382
  • 14
  • 29
  • I have read a similar discussion here but I have different goals that can't be achieved by a server upgrade: http://stackoverflow.com/questions/2205566/how-to-prevent-packet-fragmentation-for-a-httpwebrequest – jamespconnor Nov 08 '12 at 10:39
  • I don't think that this has anything to do with WCF but alot with the OS-level TCP implementation and settings... there are lots of network settings in the registry to tweak behaviour... which OS are you running on ? – Yahia Nov 08 '12 at 10:40
  • I'm running this on a variety of OSs - but thankfully all under our control - Windows 7, Windows XP (still!) and Windows Server 2008 R2. All exhibit the same behaviour. – jamespconnor Nov 08 '12 at 10:44
  • I can also reproduce this using a `HttpWebRequest`: I see one packet for the headers and one for the body (with `Expect100Continue` set to `false`, the Expect-header doesn't show up in the request). I don't know if that, or some shared base class, also gets used from the `BasicHttpBinding`, but it could be worth digging into. – CodeCaster Nov 08 '12 at 14:36
  • I've done a bit more digging and as you said CodeCaster, I can fully replicate this using a raw HttpWebRequest. If the `ContentLength` is set before `GetRequestStream()` is called, then it sends the headers when it's called. If not, it is calculated using the contents of the stream once the stream is `Close()`d and sent then. Always in a separate packet. – jamespconnor Nov 11 '12 at 14:11

1 Answers1

1

And the answer is - Can't be done with WebHttpRequest (and hence BasicHttpBinding)

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

jamespconnor
  • 1,382
  • 14
  • 29