The Transmission Control Protocol

IP is not a very reliable protocol, so it needs to have a protocol over and above it to try and add some dependability to the transactions. TCP or the Transmission Control Protocol is the protocol of choice when it comes to file transfers which need to be reliable. So HTTP, SMTP, POP 3, FTP etc. all rely on TCP/IP for data transfer. Read our WinSock tutorial for more information on how to use TCP/IP through the WinSock.

The TCP header is displayed below.

Table 1 : TCP Header format

Source Port
(16 bits)
Destination port
(16 bits)
Sequence Number
(32 bits)
Acknowledgement Number
(32 bits)
(4 bits)
(6 bits)
(6 bits)
Window Size
(16 bits)
(16 bits)
Urgent Pointer
(16 bits)
(8 bits)
(8 bits)
(16 bits)

Since TCP is required by most protocols, it has certain characteristics which make data transactions easier and faster. The first 8 bytes are ample proof of this. The PORT is an entirely imaginary entity, created just to make Internet programming easier. When you send a packet to a host on the Internet you have to stamp the TCP/IP packets with a predefined number which stands for a certain protocol. For example, port 80 ( 0x00 0x50 ) is the HTTP port. When this packet reaches the host at the other end, it quickly scans in the destination port. If the port is 80, then it sends the packet to the HTTP server running on it. If the port is 21, then the packet is giver to the FTP server and so on. This makes transfers on the Internet much faster as now the packet will only reach the server it was meant for and won't be distributed amongst all the servers running on the host. This also means that you don't require a different server for each protocol you support, you can have multiple servers running on the same machine.

These port numbers are decided by a body called IANA or Internet Assigned Numbers Association. The numbers from 0 to 1023 are reserved by IANA for any future protocols, but all the other numbers are for us to fiddle round with (Check RFC 1777 for a complete list of Port numbers). This is important because during a file transfer, even we have to have a port number, the source port. This source port is randomly chosen, but it must be greater than 1023. Additionally, you can't have two ports on your computer with the same port number.

Right after the port numbers comes the sequence number field, which is four bytes large and after that comes the Acknowledgement field, which is also four bytes large. We'll discuss the details in a moment so lets skip these two fields for now.

The byte after the Acknowledgement field has been logically devided into two halves of four bits each. The first half is the lenght of the packet and it is obtained by multiplying the number in the field with four; exactly what we did in the IP header. So the lenght of the TCP header is 6*4=24 bytes. The next four bit field is unused.

Of the next byte, the first two bits are unused and the remaining six bits constitute the flags field.

The flag bits are as shown below.

Table 2 : Flag format


The flags will be explained when we get to the discussion on sequence and acknowledgement numbers.

The two bytes following the flags make up the Windows Size field. This doesn't have anything to do with the windows you see on the screen, rather, these two bytes handle Flow Control between your computer and the server.

Flow Control is the process of data regulation between two computers. The server at the other end has greater computing capacity and a larger pipe to the Internet. So it can send me data faster than I can possibly handle it. There has to be a way for me to tell the server to pause for a moment while I process my buffers and then continue when I give the okay. That's the job of Windows Size. The two bytes in Window Size hold the maximum amount of data the other side can send us without receiving an Acknowledgement of that data from us. So is the Window size is 4kb, the server can send me four thousand bytes, without waiting for an acknowledgement of those data packets. The faster I am, the greater will be my capacity and the larger my Window Size. If I send a Window Size of 0kb, it means I want the server to stop sending while I process the data I've just received.

If you aren't clear about the acknowledgement bit in the explanation above, wait a while... Once we finish the sequence and acknowledgement numbers, re-read the explanation and you'll understand Window Size better.

After the two bytes of the Window Size, we have another two bytes for the checksum. The checksum includes the twenty byte header, the optional portion, the twelve byte pseudo header the data and the checksum itself. The actual formulae to calculate the checksum is impossible to understand unless you're a PhD in mathematics. Just cut - copy - paste the code in.

Following the checksum are the two bytes which constitute the URGENT POINTER. The Urgent Pointer holds an offset pointer to the end of some urgent data. If there are five bytes of Urgent Data...


If the Urgent Pointer is 5 then the value in the Urgent Pointer will be 5, or the last byte + 1.

The Urgent Pointer is used when some information has to reach the server ASAP. When the TCP/IP stack at the other end sees a packet using the Urgent Pointer, it is duty bound to stop all it's doing and immediately send this packet to the relevant server. Since the packet is plucked out of the processing queue and acted upon immediately, it is known as an Out Of Band (OOB) packet and the data is called Out Of Band (OOB) data. The Urgent Pointer is usually used in Telnet, where an immediate response (e.g. the echoing of characters) is desirable.

We're not using the Urgent Pointer, so we've set it to 0.

The last four bytes of the packet hold the TCP Options. The first byte of the options is the option code, the second byte is length which includes the option byte in it's calculation. The last two bytes comprise the data.

The option 2, which we put in the first packet we send to a server, means Maximum Segment Size. The two bytes of data hold the size of the largest segment we can handle without fragmentation.


Lets assume we've got this data to send across to the guy at the other end.


Now for some reason or another, we're going to send the bytes across only four bytes at a time. In other words, this data will flow across in thee packets.

The First Packet


The Second Packet


The Third Packet


Each alphabet is given a number and this will be it's sequence number.


In the very first packet we send across we set the four byte sequence number to 1 i.e. the number of the first byte in the packet and the acknowledgement number as 0. The acknowledgement number is 0 because we haven't received any bytes, so there so data to acknowledge.


The computer across the wire will respond with an ACK packet (an acknowledgement packet with the ACK flag on in the TCP header) holding an acknowledgement number of 5. This means that the computer at the other end has received all the bytes till byte 4 and it's now ready for data from byte 5 onwards. Since he hasn't sent us any data yet, his sequence number will be a random value. The sequence and acknowledgement numbers are extremely important and are the only way TCP maintains a reliable connection. If these bytes are omitted, the connection will not work.

The next packet we send will have a sequence number of 5 i.e. the number of the first byte in the packet relative to the start of the data stream. The acknowledment number will be the other guys sequence number + 1.


We will then receive an ACK with the acknowledgement number set to 9; the byte we have to start our next packet with.

We then shot off the last two bytes and wait for the ACK and when that comes, we klnow that all the bytes we've sent across has reached the computer at the other end.


The Three Way Handshake

We've covered almost everything about TCP/IP except for one thing, the actual connection! "What is it that happens when I use connect() in my code?", you might have asked during the WinSock tutorial. It's time to answer that question now.

When we try to connect to a site, using HTTP for example, we first send the server a 44 byte (TCP+IP) packet called the SYN which is a condensed version of Synchronise. The form of that packet will be identical to any normal TCP packet, except for one thing, the SYN flag will be set to 1 in the flags field. The sequence number will be any old random number e.g. 7. The acknowledgement number is usually zero.

Table 3 : Sample TCP header - SYN from client.


When the server receives our packet it will respond with an SYN-ACK. In this packet both the SYN and the ACK flags will be on. The packet will also have our sequence number + 1 in the acknowledgement field and his sequence number will have a random value.

Table 4 : Sample TCP header - SYN-ACK from server.


When we receive a SYN-ACK, we're supposed to acknowledge it and so we respond with an ACK. This packet will only be 40 bytes (TCP+IP) large as the last four bytes of the TCP header (the options) will be omitted. The sequence number will be the acknowledgement number we've just received and the acknowledgment number will be the sequence number + 1, we've just received.

Table 5 : Sample TCP header - ACK from client.


One this packet has been sent, the connection has been finalised.


SYN-Flooding is a Denial of Service technique that exploits a flaw in the implementation of TCP/IP on most UNIX machines. Once the server has received a SYN from the remote client, it sends it a SYN-ACK. After sending the SYN-ACK it waits for 40 seconds for a corresponding ACK. If it doesn't receive an ACK in that tie, it cancels the connect. Additionally, there can be only 8 concurrent connects at one time. In other words, only a maximum of 8 machines can try to connect to a server at the same time.

What a SYN-Flooder does is connect to a server and send it TCP/IP SYN packets with a bogus source IP address. When the server receives such a packet, it immediately zooms off a reply to the 'clients' machine. Unfortunately for the server, since the IP address is bogus and probably unassigned, it doesn't receive a response from anyone. So it waits for 40 seconds and then cancels the connect. If the SYN-Flooder sends a SYN packet every 5 seconds or less, it fills up the connect queue with bogus requests. The server waits for 40 second for each request and since only 8 are allowed at one time, very soon no one can connect to the server!!

This trick doesn't work as well as it once did because most companies have supplied patches that change the server's stack. Now the servers have a larger incoming queue and they wait for less time. Even then, there must still be a couple of machines runnign older operating systems that are not yet immune...

If you're through gawking at these pages, jump ahead to an explanation of programs that implement all that you've learnt under both Ethernet and PPP. Have fun!

The above tutorial is a joint effort of

Mr. Vijay Mukhi
Ms. Sonal Kotecha
Mr. Arsalan Zaidi

Back to the main page

Vijay Mukhi's Computer Institute
VMCI, B-13, Everest Building, Tardeo, Mumbai 400 034, India
Tel : 91-22-496 4335 /6/7/8/9     Fax : 91-22-307 28 59
e-mail :