A dump of the TCP packets in a brief HTTP session was taken to illustrate the steps taken when a client requests a page from a HTTP server. A step by step explanation of the output is provided to guide the reader through the steps taken.
The following is a sample dump (using tcpdump) of a HTTP request and response. The setup used when the session was captured is as follows:
hal
(192.168.0.102
). Server software is Apache 1.2.4.deep-thought
(192.168.0.103
). Browser software is Netscape Navigator 4.01.hal
is also running a DNS server, and deep-thought
has been configured to use hal
to resolve hostnames.hal
and deep-thought
are both on the same subnet of an ethernet LAN.http://hal.etc.com.au/documentation/apache/
(which consists of a HTML page with 2 images).
The output from tcpdump has been reformatted for clarity. It is in the format:
[line #] [timestamp] [arp/tcp packet details]
The timestamps are in the format hh:mm:ss.frac
.
The TCP segment details are in the form:
[originating host IP address].[originating port] > [destination host IP address].[destination port]: TCP header, e.g. 192.168.0.103.1045 > 192.168.0.102.53 indicates a packet going from port 1045 on 192.168.0.103 to port 53 on 192.168.0.102
The TCP header is shown in the following format:
[header flag] [initial sequence number]:[ending sequence number (implied)] ([size in bytes]) [acknowledgement number] [advertised window size] ([other flags])
tcpdump
output
1 14:52:49.463851 arp who-has 192.168.0.102 tell 192.168.0.103
2 14:52:49.463851 arp reply 192.168.0.102 is-at 0:a0:c9:65:14:80
3 14:52:49.463851 192.168.0.103.1045 > 192.168.0.102.53: 7+ A? hal.etc.com.au. (32)
4 14:52:49.463851 192.168.0.102.53 > 192.168.0.103.1045: 7* 1/1/1 A 192.168.0.102 (88)
5 14:52:49.543851 192.168.0.103.1046 > 192.168.0.102.80: S 7861110:7861110(0) win 8192 <mss 1460> (DF)
6 14:52:49.543851 192.168.0.102.80 > 192.168.0.103.1046: S 3595122238:3595122238(0) ack 7861111 win 32736 <mss 1460>
7 14:52:49.543851 192.168.0.103.1046 > 192.168.0.102.80: . ack 3595122239 win 8760 (DF)
8 14:52:49.653851 192.168.0.103.1046 > 192.168.0.102.80: P 7861111:7861361(250) ack 3595122239 win 8760 (DF)
9 14:52:49.663851 192.168.0.102.80 > 192.168.0.103.1046: . 3595122239:3595123699(1460) ack 7861361 win 32736 (DF)
10 14:52:49.663851 192.168.0.102.80 > 192.168.0.103.1046: P 3595123699:3595124724(1025) ack 7861361 win 32736 (DF)
11 14:52:49.663851 192.168.0.103.1046 > 192.168.0.102.80: . ack 3595124724 win 8760 (DF)
12 14:52:50.803851 192.168.0.103.1047 > 192.168.0.102.80: S 7862363:7862363(0) win 8192 <mss 1460> (DF)
13 14:52:50.803851 192.168.0.102.80 > 192.168.0.103.1047: S 3701480536:3701480536(0) ack 7862364 win 32736 <mss 1460>
14 14:52:50.803851 192.168.0.103.1047 > 192.168.0.102.80: . ack 3701480537 win 8760 (DF)
15 14:52:50.873851 192.168.0.103.1048 > 192.168.0.102.80: S 7862437:7862437(0) win 8192 <mss 1460> (DF)
16 14:52:50.873851 192.168.0.102.80 > 192.168.0.103.1048: S 2553725067:2553725067(0) ack 7862438 win 32736 <mss 1460>
17 14:52:50.873851 192.168.0.103.1048 > 192.168.0.102.80: . ack 2553725068 win 8760 (DF)
18 14:52:50.973851 192.168.0.103.1048 > 192.168.0.102.80: P 7862438:7862753(315) ack 2553725068 win 8760 (DF)
19 14:52:50.993851 192.168.0.102.80 > 192.168.0.103.1048: . ack 7862753 win 32736 (DF)
20 14:52:50.993851 192.168.0.102.80 > 192.168.0.103.1048: . 2553725068:2553726528(1460) ack 7862753 win 32736 (DF)
21 14:52:50.993851 192.168.0.102.80 > 192.168.0.103.1048: P 2553726528:2553726886(358) ack 7862753 win 32736 (DF)
22 14:52:50.993851 192.168.0.103.1048 > 192.168.0.102.80: . ack 2553726886 win 8760 (DF)
23 14:52:51.023851 192.168.0.103.1047 > 192.168.0.102.80: P 7862364:7862677(313) ack 3701480537 win 8760 (DF)
24 14:52:51.023851 192.168.0.102.80 > 192.168.0.103.1047: . 3701480537:3701481997(1460) ack 7862677 win 32736 (DF)
25 14:52:51.023851 192.168.0.102.80 > 192.168.0.103.1047: . 3701481997:3701483457(1460) ack 7862677 win 32736 (DF)
26 14:52:51.033851 192.168.0.103.1047 > 192.168.0.102.80: . ack 3701483457 win 8760 (DF)
27 14:52:51.033851 192.168.0.102.80 > 192.168.0.103.1047: P 3701483457:3701484633(1176) ack 7862677 win 32736 (DF)
28 14:52:51.033851 192.168.0.102.80 > 192.168.0.103.1047: . 3701484633:3701486093(1460) ack 7862677 win 32736
29 14:52:51.033851 192.168.0.102.80 > 192.168.0.103.1047: P 3701486093:3701486899(806) ack 7862677 win 32736 (DF)
30 14:52:51.033851 192.168.0.103.1047 > 192.168.0.102.80: . ack 3701486899 win 8760 (DF)
31 14:53:04.663851 192.168.0.102.80 > 192.168.0.103.1046: F 3595124724:3595124724(0) ack 7861361 win 32736
32 14:53:04.663851 192.168.0.103.1046 > 192.168.0.102.80: . ack 3595124725 win 8760 (DF)
33 14:53:05.993851 192.168.0.102.80 > 192.168.0.103.1048: F 2553726886:2553726886(0) ack 7862753 win 32736
34 14:53:05.993851 192.168.0.103.1048 > 192.168.0.102.80: . ack 2553726887 win 8760 (DF)
35 14:53:06.023851 192.168.0.102.80 > 192.168.0.103.1047: F 3701486899:3701486899(0) ack 7862677 win 32736
36 14:53:06.023851 192.168.0.103.1047 > 192.168.0.102.80: . ack 3701486900 win 8760 (DF)
The first thing that the WWW browser needs to do is resolve the IP address for the hostname in the URL, which is hal.etc.com.au
. To do so, it sends an ARP query to resolve the ethernet address for the configured name server (which is 192.168.0.102
). It then sends a DNS query to 192.168.0.102
to resolve the hostname to an IP address and subsequently sends a HTTP request for the document to hal
.
The HTTP server on hal
responds with the appropriate document, which was a HTML file in this case. As the HTML file was parsed by the WWW browser, it finds that two images have been linked in on that page. The WWW browser then automatically sends another two HTTP requests to hal
to retrieve these two images.
ARP broadcast query from deep-thought
to resolve the ethernet address for 192.168.0.102
.
192.168.0.102
responds with the ethernet address 00:a0:c9:65:14:80
.
deep-thought
sends a DNS query to 192.168.0.102
(port 53 is the 'well-known' port for DNS). The request identification field is set to 7, the query is of type A
(a query for host address), and the query name is "hal.etc.com.au
"
The response to the host address query. 7*
indicates that it is responding to the request for which the request identification field was 7 and that the response was authoritative. The host address for hal.etc.com.au
is 192.168.0.102
.
The DNS query and response was sent over UDP, which is the recommended method for queries. UDP is a connectionless protocol so no handshaking is necessary to establish the connection.
deep-thought
sends a TCP packet with the SYN flag set and sequence number 7861110 with 0 bytes in the data segment to port 80
on hal
(port 80
is the 'well-known' port for HTTP).
hal
responds with a TCP packet with the sequence number 3595122238 with 0 bytes in the data segment. Additionally, that TCP packet has the acknowledgement number set to 7861111 to acknowledge the receipt of the packet previously sent to hal
by deep-thought
(7861111 is derived from the sequence number of that packet = 7861110 + 1).
deep-thought
to hal
, acknowledgement number 3595122239 (3595122238 + 1), which completes the TCP handshake.
deep-thought
sends a 250 byte request to hal
. The contents of the request (which is not shown in the tcpdump output above) is as follows:
(<crlf>
is used to indicate the carriage return and line feed characters)
GET /documentation/apache/ HTTP/1.0<crlf>
Connection: Keep-Alive<crlf>
User-Agent: Mozilla/4.01 [en] (Win95; I)<crlf>
Host: hal.etc.com.au<crlf>
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*<crlf>
Accept-Language: en<crlf>
Accept-Charset: iso-8859-1,*,utf-8<crlf>
<crlf>
hal
sends a total of (1460 + 1025 = ) 2485 bytes to deep-thought
, and the acknowledgement number is set to the sequence number of the last segment received (7861361). The response (contents not shown in the tcpdump output above) consists of the following HTTP headers (278 bytes) and the HTML document requested (2207 bytes, omitted for brevity):
HTTP/1.1 200 OK<crlf>
Date: Mon, 19 Jan 1998 03:52:49 GMT<crlf>
Server: Apache/1.2.4<crlf>
Last-Modified: Wed, 08 Oct 1997 04:15:24 GMT<crlf>
ETag: "2ce0b-89f-343b08dc"<crlf>
Content-Length: 2207<crlf>
Accept-Ranges: bytes<crlf>
Keep-Alive: timeout=15, max=100<crlf>
Connection: Keep-Alive<crlf>
Content-Type: text/html<crlf>
<crlf>
[ 2207 byte HTML document deleted ]
The response was broken up into two segments because the amount of data to be transferred was greater than the maximum segment size (MSS), which was negotiated in the handshake as 1460 bytes.
deep-thought
acknowledges the receipt of the last two segments, the last finishing with the sequence number 3595124724.
hal
closes the connection approximately 15 seconds after the receipt of the previous GET on this TCP connection.
deep-thought
acknowledges receipt of the FIN.
Only a half-closure of the connection was captured. TCP is a full duplex protocol, so a proper closure requires the sending 4 messages - i.e. each end must send a segment with the FIN flag set and an ACK of the other end's FIN.
Previous versions of the HTTP protocol required that separate TCP connections be used to fetch each URL. In order to improve performance of the protocol, the latest versions of HTTP allow persistent connections (keep-alive) - multiple HTTP requests and responses can be sent on the same TCP connection. Therefore, a FIN segment is not immediately sent after the transmission of the data is completed. In this case, Apache has been configured to keep the connection alive for 15 seconds after the receipt of last request from the client, after which the connection will be terminated. Hence, it sent a FIN segment which was acknowledged by the client. The client still has not closed the connection on its end.
As the browser parses the HTML document received from the hal
, it finds that it has to load two images, and thus, spawns requests for those images.
TCP 3 way handshake to establish the connection, as per explanation above. This time, the request originates from port 1047
on deep-thought
to port 80
on hal
.
deep-thought
sends a 313 byte request to hal
for the image http://hal.etc.com.au/documentation/apache/images/sub.gif
GET /documentation/apache/images/sub.gif HTTP/1.0<crlf>
Referer: http://hal.etc.com.au/documentation/apache/<crlf>
Connection: Keep-Alive<crlf>
User-Agent: Mozilla/4.01 [en] (Win95; I)<crlf>
Host: hal.etc.com.au<crlf>
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg<crlf>
Accept-Language: en<crlf>
Accept-Charset: iso-8859-1,*,utf-8<crlf>
hal
sends a total of (1460 + 1460 + 1176 + 1460 + 806 = ) 6362 bytes, which consists of 279 bytes of header (as shown below) and 6083 bytes of binary data (the GIF image)
HTTP/1.1 200 OK<crlf>
Date: Mon, 19 Jan 1998 03:52:51 GMT<crlf>
Server: Apache/1.2.4<crlf>
Last-Modified: Wed, 08 Oct 1997 04:15:24 GMT<crlf>
ETag: "61a85-17c3-343b08dc"<crlf>
Content-Length: 6083<crlf>
Accept-Ranges: bytes<crlf>
Keep-Alive: timeout=15, max=100<crlf>
Connection: Keep-Alive<crlf>
Content-Type: image/gif<crlf>
<crlf>
deep-thought
to hal
, acknowledgement of TCP segments sent.
See TCP connection termination explanation above.
TCP 3 way handshake, as per explanation above. The request originates from port 1048
on deep-thought
to port 80
on hal
.
deep-thought
sends a 315 byte request to hal
for the image http://hal.etc.com.au/documentation/apache/images/index.gif.
GET /documentation/apache/images/index.gif HTTP/1.0<crlf>
Referer: http://hal.etc.com.au/documentation/apache/<crlf>
Connection: Keep-Alive<crlf>
User-Agent: Mozilla/4.01 [en] (Win95; I)<crlf>
Host: hal.etc.com.au<crlf>
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg<crlf>
Accept-Language: en<crlf>
Accept-Charset: iso-8859-1,*,utf-8<crlf>
<crlf>
hal
acknowledges the receipt of the TCP segment
hal
sends a total of (1460 + 358 = ) 1818 bytes to deep-thought
, which consists of a 278 byte header (shown below) followed by 1540 bytes of binary data (the GIF image).
HTTP/1.1 200 OK<crlf>
Date: Mon, 19 Jan 1998 03:52:50 GMT<crlf>
Server: Apache/1.2.4<crlf>
Last-Modified: Wed, 08 Oct 1997 04:15:24 GMT<crlf>
ETag: "61a84-604-343b08dc"<crlf>
Content-Length: 1540<crlf>
Accept-Ranges: bytes<crlf>
Keep-Alive: timeout=15, max=100<crlf>
Connection: Keep-Alive<crlf>
Content-Type: image/gif<crlf>
<crlf>
deep-thought
acknowledges the receipt of the 1818 bytes sent.
See TCP connection termination explanation above.