Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does TCP send a SYN/ACK on every packet or only on the first connection?

I have a TCP server that listens for an incoming client, then sends it one packet of data every second. I was wondering, does the SYN/ACK packet only get sent on initial connection, so it looks like this:

<client connect> SYN ACK DATA DATA DATA <client disconnect> 

Or does it get sent with every packet, like this?

<client connect> SYN ACK DATA  SYN ACK DATA  SYN ACK DATA <client disconnect> 

Also, if it's the first case, are there any benefits of UDP over TCP if you just keep the connection open over a long period of time?

like image 805
Daniel T. Avatar asked Aug 30 '10 21:08

Daniel T.


People also ask

How does TCP work SYN-ACK?

The host, generally the browser, sends a TCP SYNchronize packet to the server. The server receives the SYN and sends back a SYNchronize-ACKnowledgement. The host receives the server's SYN-ACK and sends an ACKnowledge. The server receives ACK and the TCP socket connection is established.

How often does TCP ACK?

RFC 5681 mandates that an acknowledgement be sent for at least every other full-size segment, and that no more than 500ms expire before any segment is acknowledged. The resulting behavior is that, for longer transfers, acknowledgements are only sent for every two segments received ("ack every other").

Does TCP wait for ACK before sending next packet?

Application does pass the message to TCP layer, but the operating system does not send it until an ACK from the client is received.

How long does TCP wait for SYN-ACK?

Therefore in case of SYN or SYN/ACK packets getting lost TCP waits 3 seconds (or longer for further back-offs) before retransmitting them. Especially for short-lived flows, this delay can significantly degrade the performance.


1 Answers

It's kinda like:

+-------------------------------------------------------+ |     client           network            server        | +-----------------+                +--------------------| |    (connect)    | ---- SYN ----> |                    | |                 | <-- SYN,ACK -- |     (accepted)     | |   (connected)   | ---- ACK ----> |                    | \_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/  when client sends... \_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/ |                 |                |                    | |     (send)      | ---- data ---> |                    | |                 | <---- ACK ---- |  (data received)   | \_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/  when server sends... \_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/ |                 |                |                    | |                 | <--- data ---- |       (send)       | | (data received) | ---- ACK ----> |                    | \_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/  ...and so on, til the connection is shut down or reset 

SYN starts a connection; you'll usually only see it when the connection's being established. But all data being sent via TCP requires an ACK. Every byte sent must be accounted for, or it will be retransmitted (or the connection reset (closed), in severe cases).

Actual connections aren't usually exactly like the diagram above, though, for two reasons:

  • ACKs can build up, so one ACK can acknowledge everything received up to that point. That means you can acknowledge two or more sends with one ACK.
  • An ACK is simply a flag and field in a TCP header. Sending one requires at least a header's worth of bandwidth, plus whatever the lower layers tack on. But data segments already include all that...so if you're sending data, you can send an ACK at the same time for free.

Most TCP/IP stacks try to reduce the number of naked ACKs without unduly risking retransmission or a connection reset. So a conversation like this one is quite possible:

\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/ |                 |                |                    | |                 | <--- data ---- |       (send)       | | (data received) |                |                    | |     (send)      | -- data,ACK -> |                    | |                 |                |  (data received)   | |                 | <- data,ACK -- |       (send)       | | (data received) |                |                    | |  (wait a bit)   | <--- data ---- |       (send)       | | (data received) |                |                    | |     (send)      | -- data,ACK -> |                    | |                 |                |  (data received)   | |     (send)      | ---- data ---> |   (wait a bit)     | |                 |                |  (data received)   | |                 | <- data,ACK -- |       (send)       | | (data received) |                |                    | |  (wait a bit)   |   (dead air)   |                    | |                 | ---- ACK ----> |                    | \_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/ 

As for UDP, there's no built-in concept of SYN and ACK -- UDP is by nature "unreliable", and not connection-oriented, so the concepts don't apply as much. Your acknowledgement will usually just be the server's response. But some application-layer protocols built on top of UDP will have some protocol-specific way of acknowledging data sent and received.

like image 182
cHao Avatar answered Sep 22 '22 22:09

cHao