here's how a TCP packet is structured (if it's sent over Ethernet):
+-+-+-+-+-+-+-+-+-- | Ethernet header | +-+-+-+-+-+-+-+-+-- | IP header | +-+-+-+-+-+-+-+-+-- | TCP header | +-+-+-+-+-+-+-+-+-+ | packet contents | +-+-+-+-+-+-+-+-+-+
that's why we call it "TCP/IP" -- TCP packets basically always have an IP header.
Every TCP connection starts with this 3-way handshake:
a very common symptom of a firewall issue is seeing
packets being sent but no
ACK being sent back.
email is sent over SMTP, which uses TCP
FTP, POP3, HTTP/1, HTTP/2, websockets, and a bunch of other Internet protocols also use TCP
An HTTP request/response is a single TCP connection -- the client sends a HTTP request, then the server sends a response.
For example, websockets use TCP to let the client and server send data back & forth as much as they want.
packets always have a maximum size (often 1500 bytes), so often a TCP message needs to be split into many packets
there's no guarantee that network packets will arrive in the order you sent them.
Linux, Mac, Windows, etc all have TCP implementations. Almost any networking code you run on a desktop computer is going to use the OS's TCP implementation.
If you want, you can write your own TCP implementation though!
Every packet's sequence number tells you its position in the overall stream. The sequence number counts bytes, not packets. Here's an example set of packet contents & sequence numbers (each character is 1 byte):
+-+-+-+-+-+-+-+-+-+-+- | contents | seq # | +-+-+-+-+-+-+-+-+-+-+- | hello I | 0 | +-+-+-+-+-+-+-+-+-+-+- | pple! | 17 | +-+-+-+-+-+-+-+-+-+-+- | 'm a pinea | 7 | +-+-+-+-+-+-+-+-+-+-+-
when put in the correct order, these packets rearrange to "hello I'm a pineapple!"
usually the first sequence number in a connection is a big number like
1737132723, and all the other sequence numbers are
relative to that number. So you have to subtract the first sequence
If you look at TCP packets in Wireshark/tcpdump they'll do the subtraction to make it look like the sequence number starts at 0 so it's easier to read.
For example, if a server has received a packet with sequence number 1200 and has also received all the earlier packets, it'll send an ACK packet with the sequence number set to 1200.
if the client (or server) doesn't get an ACK for a packet it sent within a certain amount of time, it'll retry sending the packet.