In several Internet sources I've seen a general recommendation to disable sending Expect: 100-continue HTTP header in order to increase performance if the client is NOT actually going to send a large body.
However, testing the following code reveals that sending the header makes overall time decrease by ~50ms in average.
var hc = new HttpClient();
hc.DefaultRequestHeaders.ExpectContinue = ?;
hc.BaseAddress = new Uri("http://XXX/api/");
var r = new HttpRequestMessage(HttpMethod.Post, new Uri("YYY", UriKind.Relative))
{
Content = new StringContent("{}", Encoding.UTF8, @"application/json")
};
var tt = hc.SendAsync(r).Result;
tt.Content.ReadAsStringAsync().Result.Dump();
hc.Dispose();
Here is the WireShark dump for request with Expect: 100-continue
1 0.000000000 ss.ss.ss.176 dd.dd.dd.150 TCP 66 54515→80 [SYN] Seq=0 Win=8192 Len=0 MSS=1260 WS=4 SACK_PERM=1
2 0.342137000 dd.dd.dd.150 ss.ss.ss.176 TCP 66 80→54515 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1380 WS=1 SACK_PERM=1
3 0.342687000 ss.ss.ss.176 dd.dd.dd.150 TCP 54 54515→80 [ACK] Seq=1 Ack=1 Win=66780 Len=0
4 *REF* ss.ss.ss.176 dd.dd.dd.150 HTTP 272 POST /XXX/api/YYY HTTP/1.1
5 0.361158000 dd.dd.dd.150 ss.ss.ss.176 HTTP 79 HTTP/1.1 100 Continue
6 0.361846000 ss.ss.ss.176 dd.dd.dd.150 TCP 56 54515→80 [PSH, ACK] Seq=219 Ack=26 Win=66752 Len=2
7 0.705497000 dd.dd.dd.150 ss.ss.ss.176 HTTP 461 HTTP/1.1 200 OK (application/json)
8 0.726029000 ss.ss.ss.176 dd.dd.dd.150 TCP 54 54515→80 [FIN, ACK] Seq=221 Ack=433 Win=66348 Len=0
9 1.067923000 dd.dd.dd.150 ss.ss.ss.176 TCP 54 80→54515 [FIN, ACK] Seq=433 Ack=222 Win=65535 Len=0
10 1.068466000 ss.ss.ss.176 dd.dd.dd.150 TCP 54 54515→80 [ACK] Seq=222 Ack=434 Win=66348 Len=0
The same request without the header:
11 9.300455000 ss.ss.ss.176 dd.dd.dd.150 TCP 66 54516→80 [SYN] Seq=0 Win=8192 Len=0 MSS=1260 WS=4 SACK_PERM=1
12 9.640626000 dd.dd.dd.150 ss.ss.ss.176 TCP 66 80→54516 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1380 WS=1 SACK_PERM=1
13 9.641393000 ss.ss.ss.176 dd.dd.dd.150 TCP 54 54516→80 [ACK] Seq=1 Ack=1 Win=66780 Len=0
14 *REF* ss.ss.ss.176 dd.dd.dd.150 HTTP 250 POST /XXX/api/YYY HTTP/1.1
15 0.406794000 dd.dd.dd.150 ss.ss.ss.176 TCP 54 80→54516 [ACK] Seq=1 Ack=197 Win=65535 Len=0
16 0.406963000 ss.ss.ss.176 dd.dd.dd.150 TCP 56 54516→80 [PSH, ACK] Seq=197 Ack=1 Win=66780 Len=2
17 0.749589000 dd.dd.dd.150 ss.ss.ss.176 HTTP 461 HTTP/1.1 200 OK (application/json)
18 0.769053000 ss.ss.ss.176 dd.dd.dd.150 TCP 54 54516→80 [FIN, ACK] Seq=199 Ack=408 Win=66372 Len=0
19 1.109276000 dd.dd.dd.150 ss.ss.ss.176 TCP 54 80→54516 [FIN, ACK] Seq=408 Ack=200 Win=65535 Len=0
20 1.109742000 ss.ss.ss.176 dd.dd.dd.150 TCP 54 54516→80 [ACK] Seq=200 Ack=409 Win=66372 Len=0
Same results were received for IIS 7.5, IIS 8.0
The questions are:
- What makes the request with the Expect header execute faster, when theoretically the opposite shall take place?
- Is it always the case that the body of POST request goes within a separate TCP packet (I've looked through only a couple of samples, there this is true)? Here I mean why TCP packet at line 14 in dump does not contain the data (POST body) that was sent in TCP packet at line 16?