114

The TCP 3-way handshake works like this:

Client ------SYN-----> Server
Client <---ACK/SYN---- Server
Client ------ACK-----> Server

Why not just this?

Client ------SYN-----> Server
Client <-----ACK------ Server
  • 24
    Why do we even need a handshake? Why can't the message be sent with the first packet? – Mehrdad Nov 4 '15 at 20:50
  • 4
    If you want to skip the handshake you could use UDP instead. – OzNetNerd Nov 4 '15 at 22:26
  • 5
    @Mehrdad, if you have a question of your own, please use the Ask Question link at the top of the page to post your own. – YLearn Nov 4 '15 at 23:12
  • 39
    @YLearn: Sorry, it's not really a question of my own, but rather it was to motivate readers to give answers that dig a little deeper than what is literally stated in the question. – Mehrdad Nov 5 '15 at 0:03
  • 3
    Don't forget about TCP Fast Open (RFC 7413) – Alnitak Nov 6 '15 at 23:25
147

Break down the handshake into what it is really doing.

In TCP, the two parties keep track of what they have sent by using a Sequence number. Effectively it ends up being a running byte count of everything that was sent. The receiving party can use the opposite speaker's sequence number to acknowledge what it has received.

But the sequence number doesn't start at 0. It starts at the ISN (Initial Sequence Number), which is a randomly chosen value. And since TCP is a bi-directional communication, both parties can "speak", and therefore both must randomly generate an ISN as their starting Sequence Number. Which in turn means, both parties need to notify the other party of their starting ISN.

So you end up with this sequence of events for a start of a TCP conversation between Alice and Bob:

Alice ---> Bob    SYNchronize with my Initial Sequence Number of X
Alice <--- Bob    I received your syn, I ACKnowledge that I am ready for [X+1]
Alice <--- Bob    SYNchronize with my Initial Sequence Number of Y
Alice ---> Bob    I received your syn, I ACKnowledge that I am ready for [Y+1]

Notice, four events are occurring:

  1. Alice picks an ISN and SYNchronizes it with Bob.
  2. Bob ACKnowledges the ISN.
  3. Bob picks an ISN and SYNchronizes it with Alice.
  4. Alice ACKnowledges the ISN.

In actuality though, the middle two events (#2 and #3) happen in the same packet. What makes a packet a SYN or ACK is simply a binary flag turned on or off inside each TCP header, so there is nothing preventing both of these flags from being enabled on the same packet. So the three-way handshake ends up being:

Bob <--- Alice         SYN
Bob ---> Alice     SYN ACK 
Bob <--- Alice     ACK     

Notice the two instances of "SYN" and "ACK", one of each, in both directions.


So to come back to your question, why not just use a two-way handshake? The short answer is because a two way handshake would only allow one party to establish an ISN, and the other party to acknowledge it. Which means only one party can send data.

But TCP is a bi-directional communication protocol, which means either end ought to be able to send data reliably. Both parties need to establish an ISN, and both parties need to acknowledge the other's ISN.

So in effect, what you have is exactly your description of the two-way handshake, but in each direction. Hence, four events occurring. And again, the middle two flags happen in the same packet. As such three packets are involved in a full TCP connection initiation process.

  • 4
    Why do we need ISNs at all? Humans don't need it, why do computers? Is there a proof of this, or do we just have them because they're convenient? – Mehrdad Nov 4 '15 at 20:52
  • 16
    @Mehrdad: You need sequence numbers for retransmissions to work properly (or indeed at all). The ISN can't just be zero because of sequence prediction attacks. – Kevin Nov 4 '15 at 21:04
  • 4
    @Mehrdad The chat room doesn't necessarily have to be 'real time', we can leave messages for each other. The reason I thought to direct it elsewhere is because you are now asking a different question. The OP asked "why is it a 3 way handshake instead of 2", but now you questioning "why do we need Sequence numbers at all", which is different. Rather than derail this thread, I thought we should discuss the other question in chat. Alternatively, you can post a new question, I'm sure it will net some good answers. – Eddie Nov 4 '15 at 22:19
  • 4
    Great, concise answer. Reading "ACK SYN" feels fundamentally wrong but you even explained that so +1. – Lilienthal Nov 5 '15 at 12:52
  • 2
    According to RFC 793, Transmission Control Protocol: "The principle reason for the three-way handshake is to prevent old duplicate connection initiations from causing confusion." – Ron Maupin Nov 5 '15 at 18:05
22

The three-way handshake is necessary because both parties need to synchronize their segment sequence numbers used during their transmission. For this, each of them sends (in turn) a SYN segment with a sequence number set to a random value n, which then is acknowledged by the other party via a ACK segment with a sequence number set to n+1.

  • Why is the acknowledgement needed? – Paŭlo Ebermann Nov 4 '15 at 21:18
  • 4
    @PaŭloEbermann: Because otherwise the Server has no idea if the client ever received the SYN, and it's important that the client receives that. – Mooing Duck Nov 4 '15 at 21:21
  • 2
    @PaŭloEbermann And to prove it, the ACK step is to acknowledge with [X+1]. -- quoted from Eddie's comment to his answer. – smwikipedia Nov 5 '15 at 8:22
14

In order for the connection to work, each side needs to verify that it can send packets to the other side. The only way to be sure that you got a packet to the other side is by getting a packet from them that, by definition, would not have been sent unless the packet you sent got through. TCP essentially uses two kinds of messages for this: SYN (to request proof that this packet got through) and ACK (which only gets sent after a SYN gets through, to prove that the SYN got through). There's actually a third kind of message, but we'll get to that in a moment.

Before the connection starts, neither side really knows anything about the other. The client sends a SYN packet to the server, to request proof that its messages can get through. That doesn't tell either person anything, but it's the first step of the handshake.

If the SYN gets through, then the server knows that the client can send packets to it, because, well, it just happened. But that doesn't prove that the server can send packets back: clients can send SYNs for lots of reasons. So the server needs to send two messages back to the client: an ACK (to prove that the SYN got through) and a SYN (to request an ACK of its own). TCP combines these two messages into one -a SYN-ACK message, if you will- to reduce network traffic. This is the second step of the handshake.

Because a SYN-ACK is an ACK, the client now knows for sure that it can send packets to the server. And because a SYN-ACK is a SYN, it also knows that the server wants proof that this message got through. So it sends back an ACK: just a plain ACK this time, because it doesn't need proof anymore that its packets can get through. This is the final step of the handshake: the client now knows that packets can go both ways, and that the server is just about to figure this out (because it knows the ACK will go through).

Once that ACK gets through, now the server knows that it can send packets to the client. It also knows that the client knows this, so it can start sending data right away. The handshake is complete. We have a good channel.

Well, strictly speaking, we can't be certain we have a good channel. Just because this sequence of packets got through does not strictly guarantee that others will. We can't prove that without sending an infinite number of SYNs and ACKs, and then nothing else would ever get done, so that's not really a practical option. But in practice, three steps turns out to be good enough for most purposes.

  • This is untrue: "an ACK (which only gets sent in response to SYNs, and thus proves that the SYN got through)." Only the first packet sent from each end has the SYN flag set, and all packets other than the very first packet of the 3-way handshake have the ACK flag set. The first packet can't ACK because the second party hasn't SYNed yet, but every packet after the first must ACK whatever has already been received from the other end, whether any data be sent back or not. – Monty Harder Oct 31 '16 at 14:43
  • Thanks. Rewording: ACKs get sent once a SYN gets through, rather than only being sent in response to SYNs. – The Spooniest Oct 31 '16 at 15:53
  • This is the best answer which can explain logically why we even need the third message. Thanks, Spooniest. – Parth Patel Mar 10 at 18:55
7

Actually, a 3-way handshake isn't the only means of establishing a TCP connection. Simultaneous SYN exchange is also allowed: http://www.tcpipguide.com/free/t_TCPConnectionEstablishmentProcessTheThreeWayHandsh-4.htm

That could be seen as a sort of double 2-way handshake.

  • 1
    Good point, however this is very rare as both devices will have to be using the same source/destination port and both devices will need to send a SYN before the other receives the SYN. Even when it does occur, it involves four packets being sent, which is more than the three packets required by the traditional 3-way handshake; ultimately only the possibility of being slightly faster to set up in terms of overall time at the cost of less overall efficiency (requires 33% more packets to be transmitted). – YLearn Nov 5 '15 at 16:39
4

TCP connection is bidirectional. What this means is that it actually is a pair of one-way connections. The initiator sends SYN, the responder sends ACK: one simplex connection begins. "Then" the responder sends SYN, the initiator sends ACK: another simplex connection begins. Two simplex connections form one duplex TCP session, agree? So logically there are four steps involved; but because SYN and ACK flags are different "fields" of TCP header, they can be set simultaneously - the second and the third steps (of the four) are combined, so technically there are three packet exchanges. Each simplex (half-)connection uses 2-way exchange, as you proposed.

2

If Server and Client want to create a connection, they need confirm four things:

  1. Server need to confirm he can receive packet from Client
  2. Client need to confirm he can receive packet from Server

  3. Client need to confirm a thing: Server can receive packet from Client

  4. Server need to confirm a thing: Client can receive packet from Server

After Client ------SYN-----> Server, rule 1 is confirmed.

After Client <---ACK/SYN---- Server, rule 2 and 3 is confirmed.

So, there need a third packet to confirm rule 4.

1

It is not necessary at all. It is obvious that a short message should only require one packet to the server which includes the start + message, and one packet back acknowledging it.

The previous answers just describe the system without discussing the need for random sequence numbers etc. in the first place. The original question was about the design of TCP itself -- obviously if you use the TCP protocol then you need three messages because that is the protocol. But why was TCP designed that way in the first place?

I believe the original idea was that there was no distinction between clients and servers. Both knew the other's ports in a bidirectional manner, and either could start the conversation. And that required Syns etc.

But this is not, of course, how it is used today. The server listens on a well known port and does and "accept", the client port number is ephemeral. I do not even think it is possible for a server waiting on an "accept" to send a request to another on the same client port number in normal operating systems.

(Note that this is about bidirectional initiation of the connection, which is never done today. That is quite different from sending bidirectional messages down a connection once established.)

To work around the TCP inefficiency, we use protocols like HTTP 1.1 which can reuse the same connection for multiple requests, and thus avoid the TCP handshake which was not necessary in the first place.

But Http 1.1 is relatively new. And SSL/TLS needed a way to reuse session from the beginning due to the cost of the PKI algorithms. So that protocol includes its own session reuse mechanism which runs on top of Http 1.1 which runs on top of TCP.

Such is the way with software. Fudges on kludges which when combined, produce an acceptable result.

  • Anything above OSI layer-4 (e.g. HTTP, FTP, etc.) is explicitly off-topic here. In layers 1 to 4, there is no such thing as client/server. TCP is a connection between peers. Yes, upper layer protocols create a client/server relationship, but that is off-topic here. – Ron Maupin May 23 '16 at 2:10
  • 1
    By the way, HTTP uses TCP, so the TCP handshake is still necessary. Read RFC 793 TRANSMISSION CONTROL PROTOCOL to undestand why. Protocols like HTTP require the application to do the multiplexing that TCP would normally do for the application. – Ron Maupin May 23 '16 at 2:18
  • @RonMaupin The original question was why? And the answer is to support a use case that is never used by the upper level layers in practice. So, seems pretty relevant. – Tuntable May 23 '16 at 2:18
  • @RonMaupin Yes, HTTP uses TCP. Which I have clarified, thanks. But that does not make the TCP handshake necessary in any deep sense. – Tuntable May 23 '16 at 2:20
  • 1
    The applications and application-layer protocols are explicitly off-topic here. @Eddie answered the question, and if you read and understand the TCP RFC, you will get why the handshake is necessary. I don't think it adds anything for you to claim, without any support, that the handshake is not necessary, when it clearly is. – Ron Maupin May 23 '16 at 2:21
1

After reading answer of Eddie (accepted as correct), there are still question why 1st host can not assign both ISN's with random numbers and 2nd just accept it. Real reason of using 3-way handshake is to avoid half-connections. Half connection scenario in 2-way handshake:
1) Client ---SYN--> Server
2) Client changes his mind and doesn't want to connect anymore
3) Client <-X-ACK-- Server //ACK was lost
Server doesn't see resent SYN, so he thinks that client got his ACK and connection is established. As a result Server has connection that will never be closed

  • Actually, if a host (clients and servers are an application concept about which TCP knows nothing) receives an ACK or any traffic on a non-existent connection (step 3 in your scenario), it will send a RST, not ignore the received segment. – Ron Maupin May 15 '18 at 14:42
  • @RonMaupin Then let's assume situation when ACK packet was lost. – Sanzhar Yeleuov May 15 '18 at 16:34
  • If the ACK is lost, then the initiated connection in step 1 will time out. RFC 793 has a full explanation of all types of scenarios, including diagrams. – Ron Maupin May 15 '18 at 16:38
  • @RonMaupin I mean if scenario from my post remain same, only thing that changed, that ACK was lost. – Sanzhar Yeleuov May 15 '18 at 16:43
  • It's all in the RFC. Until a connection is open, any traffic received will result in a RST. The three-way handshake negotiates the connection parameters, so the "server" cannot send anything back to the "client" but it's SYN/ACK until it receives an ACK from the "client". If the "server" SYN/ACK back to the "client" is lost, the "server" will try again. The RFC explains all this. – Ron Maupin May 15 '18 at 16:49

protected by Ron Maupin May 15 '18 at 14:43

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.