We all know that TCP is a streaming protocol.
Unlike UDP, which guarantees that the whole client message will be delivered to server as a single datagram (we're talking about transport layer, so avoid MTU at the moment), TCP can fragment one "message" (data that was passed to the send function) into several smaller packets so we have to use our own delimiters as a messages' borders.
The question is -- how TCP chooses which data should be fragmented and by which size? Is there any common / standard methods that it uses?
TCP uses a parameter called Maximum Segment Size:
The maximum segment size (MSS) is a parameter of the options field of the TCP header that specifies the largest amount of data, specified in bytes, that a computer or communications device can receive in a single TCP segment. It does not count the TCP header or the IP header. The IP datagram containing a TCP segment may be self-contained within a single packet, or it may be reconstructed from several fragmented pieces; either way, the MSS limit applies to the total amount of data contained in the final, reconstructed TCP segment.
The default TCP Maximum Segment Size is 536. Where a host wishes to set the maximum segment size to a value other than the default, the maximum segment size is specified as a TCP option, initially in the TCP SYN packet during the TCP handshake. The value cannot be changed after the connection is established.
If path MTU discovery is enabled, MSS is set to that minus TCP headers size.
On Linux TCP_MAXSEG socket option controls the parameter:
if this option is set before connection establishment, it also changes the MSS value announced to the other end in the initial packet. Values greater than the (eventual) interface MTU have no effect. TCP will also impose its minimum and maximum bounds over the value provided.
Related
I have seen the tcp length is changing but not sure what made it,
32bytes
40bytes
Is it possible to set this fixed as 32bytes?
----updated----
I am not sure if MSS related to TCP length, which means 1460 gives 32 bytes?
TCP header length can vary for a number of reasons.
The usual value is 40 bytes, but options such as SACK can result in longer headers, as specific sections of a stream are ACKed where packets have been dropped (or overly delayed).
HTTP in general has no interest or control over the size of the underlying transport (TCP) header. These things tend to be set by the operating system TCP/IP stack, although some can be altered with iocontrols to the sockets.
I've noticed in wireshark that I'm able to send 4096 bytes of data to a HTTP webserver (from uploading a file) however the server only seems to be acknowledging data 1460 bytes at a time. Why is this the case?
The size of TCP segments is restricted to the MSS (Maximum Segment Size), which is basically the MTU (Maximum Transmission Unit) less the bytes comprising the IP and TCP overhead. On a typical Ethernet link, the MTU is 1500 bytes and basic IP and TCP headers comprise 20 bytes each, so the MSS is 1460 (1500 - 20 - 20).
If you're seeing packets indicated with a length field of 4096 bytes, then it almost certainly means that you're capturing on the transmitting host and Wireshark is being handed the large packet before it's segmented into 1460 byte chunks. If you were to capture at the receiving side, you would see the individual 1460 byte segments arriving and not a single, large 4096 byte packet.
For further reading, I would encourage you to read Jasper Bongertz's blog titled, "The drawbacks of local packet captures".
TCP by default uses path MTU discovery:
When system send packet to the network it set don't fragment flag (DF) in IP header
When IP router or you local machine see DF packet that should be fragmented to match MTU of the next hop link it sends feedback (RTCP fragmentation need) that contains new MTU
When system receives fragmentation needed ICMP it adjusts MSS and send data again.
This procedure is performed to reduce overall load on the network and increase probability of each packet delivery.
This is why you see 1460 packets.
Regarding to you question: the server only seems to be acknowledging data 1460 bytes at a time. Why is this the case?
TCP keep track window that defines "how many bytes of data you can send without acknowledge". Its purpose is to provide flow control mechanisms (sender can't send too much data that can't be processed) and congestion control mechanisms (sender can't send too much data to overload network). Window is defined by receiver side and may be increased during connection when TCP will estimate real channel bandwidth. So you may see one ACK that acknowledges several packets.
In TCP/IP, we have MSS and MTU when sending and receiving packets.
MTU is an IP layer concept, which is determined by the underlying hardware. It shows the maximum data size that an IP layer packet can contain during one transmission.
MSS is a TCP layer concept, which is limited by the MTU, showing that the TCP data stream will be fragmented into MSS-size packets.
Our protocol lies on top of TCP, and each protocol will define its own packet. One example is MySQL, which defines its packet size up to 2^24-1, that is around 16M. When the big enough protocol packet comes to TCP, it will be fragmented according to MSS.
Assume that a client needs to send DATA1 and DATA2 to server. DATA2 size is bigger than MSS, and DATA2 will be fragmented into DATA2_1, DATA2_2. As the packets will be handled by the IP layer, so the time that each packet arrives at server might not be the same as that when the client sends them.
So I think the sequence of packets' arriving might be the following:
DATA1 DATA2_1, DATA2_2
DATA1, DATA2_1, DATA2_2
DATA1, DATA2_2, DATA2_1
In the first case, the server receives DATA1 and DATA2_1 in one tcp packet and then another packet contains DATA2_2 arrives.
In the second case, the server receives DATA1, DATA2_1 and DATA2_2 in three packets.
In the third case, the server first receives DATA2_2 and then DATA2_1.
My question:
Is the third case possible?
If yes, it disobeys that TCP is a stream protocol, and stream protocol should be ordered. And even this does not break the stream rule, how to handle this scenario?
If no, how TCP makes the disordered packets into its original order?
It is possible to receive that sequence over the network, however the TCP implementation will hide that detail from your application and only feed the data to you in stream order. (In fact since fragmentation happens at the IP layer it won't even be shown to the TCP layer until the second part has arrived also)
The fact that received packets have to be held in a buffer even after receiving them in some cases like this is why you will see people referring to UDP as better for lower latency applications: you can receive datagrams out of order with UDP and it's up to your application to figure out how to deal with that possibility.
Is the third case possible.
Yes, of course.
If so, it disobeys that TCP is a stream protocol ...
No it doesn't.
Your cases concern arrival of IP packets into a host. TCP being a stream protocol is about delivery of data into an application.
The packet fragments get reassembled in the correct order by the IP layer, and the packets get reassembled into segments in the correct order by TCP, and the now correctly ordered data stream is delivered to the application.
I am building an app where my phone frequently send data to my server. Since I would be using my mobile data, I was wondering how much data it cost to set up (and tear down?) a TCP connection to my server.
TCP Three-way handshake
Device 1 sends its TCP sequence number and maximum segment size to Device 2.
Device 2 responds by sending its sequence number and maximum segment size to Device 1.
Device 1 acknowledges receipt of the sequence number and segment size information.
Each packet is composed of an IP header and data (payload). In this case, the data section contains TCP. The TCP header contains various fields including the source and destination ports, sequence and acknowledgment numbers, window size, TCP flags, urgent pointer, and reserved bits.
Like the IP header, the TCP header may also contain options. (Note that TCP options and IP options are two different things.) Because the TCP options change the length of the TCP header, the length is set in the header.
IPv4 header is five 4-byte chunks, or 20 bytes total.
TCP typically usually uses 24 bytes of the header for handshake (first two packets) and about 20 for normal packet transmission.
Maximum Segment Size (MSS): 4 bytes
Window Scale (WSCALE): 3 bytes
Timestamp (TS): 10 bytes
No Operation (NOP): 1 byte
Selective Acknowledgment Permitted (SackOK): 2 bytes
Selective Acknowledgment Data: 10 bytes (plus 8 bytes for each additional pair of sequence numbers)
Terminating a Connection
Even though establishing a connection using 3-way handshake requires only 3 packets to be transmitted, tearing down one requires 4!
In the first frame the client sends a FIN that is accompanied by an ACK. The FIN parameter is set, it will inform the server that it has no more data to send.
The response (2nd frame) would be simply the server acknowledging the FIN sent from the client.
Even though TCP has established connections between the two computers, the connections are still independent of one another. Therefore, the server will also transmit a FIN to the client.
You guessed it right ... the client would ACK the FIN of the server in the last forth packet.
The offset of each of the frames is typically 20 bytes.
To sum it up.
Establishing a connection: ~ 128-136 bytes
Tearing down a connection: ~ 160 bytes
If you plan to use TLS / SSL handshake, this is estimated to be between 4.5k-6.5k.
Note: Please also take a look at TCP/IP Header Compression
Sources:
Inside the TCP Handshake
Explanation of the Three-Way Handshake via TCP/IP
Studying Normal Traffic, Part Three: TCP Headers | Symantec Connect
I wonder how MSS is set in SYN packet? Is it a fixed value in one operating system or the value could be changed in the same operating system? I know that the value is different in different operating systems. Also is the MSS value in SYN related to hardware configuration?
Thanks.
RFC 879 describes how MSS is used and specified.
In short, MSS is specified during TCP handshake via SYN packet. However, this value can later be changed by OS itself or by setting a protocol option.
You can set option TCP_MAXSEG via setsockopt.
Whilst the value of MSS in SYN and SYNACK packets are set by the initiator and responder side, respectively, a widely used practice known as MSS clamping can result in the MSS being altered by a network element on the path - this is often used to reduce the MSS of all connections going over some sort of tunnelled link. For example PPPoE is commonly used on residential broadband and requires an MTU of 1492 and corresponding IPv4 MSS of 1452 so whilst the SYN may leave your machine with an MSS of 1460 (assuming you're using Ethernet with an MTU of 1500) but once it passes the MSS clamping ISP router the MSS in SYN packet will subsequently be changed to 1452, and likewise for the incoming/responder's SYNACK packet so the connection proceeds with reduced MSS of 1452. This practice seems to be used instead of Path MTU Discovery which relies upon the use of ICMP Fragmentation Needed responses from the network as these can be lost on poorly configured networks and by certain load balancing techniques.