IP, port, TCP và UDP

4 câu hỏi~25 phútTừ khóa: IP, port, ephemeral port, 3-way handshake, 4-tuple, TCP vs UDP, 0.0.0.0, 127.0.0.1, ss -ltnp

Tiếp đi. IP với port khác nhau chỗ nào, mình hay nói "gọi 10.0.1.4:8080" mà chưa hiểu rõ.

Bài trước có bản đồ. Giờ zoom vào chặng 2: developer gọi order-service trên Azure VM có private IP 10.0.1.4, app listen port 8080.

1. Bài toán

curl http://10.0.1.4:8080/orders/123

Trên cùng VM đó còn có Nginx (80/443), SSH (22). Làm sao gói tin biết phải tới đúng order-service chứ không phải SSH?

2. Vấn đề

3. Giải pháp: IP + port + giao thức transport

IP   = địa chỉ tòa nhà      10.0.1.4
Port = số phòng             8080 (order-service), 22 (SSH), 443 (Nginx)
TCP/UDP = cách giao hàng    có ký nhận (TCP) / ném qua cửa (UDP)

4. Từng bước

Bước 1: Xem app đang listen gì (trên VM):

sudo ss -ltnp
State   Local Address:Port   Process
LISTEN  0.0.0.0:22           sshd
LISTEN  0.0.0.0:80           nginx
LISTEN  127.0.0.1:8080       java   <-- chỉ nhận từ chính máy này
LISTEN  *:8080               java   (nếu bind tất cả interface)

-l listening, -t TCP, -n không đổi số thành tên, -p process.

Bước 2: Chọn bind address trong application.yml:

server:
  port: 8080
  address: 0.0.0.0     # mọi interface (mặc định của Spring Boot)
  # address: 127.0.0.1 # chỉ loopback: dùng khi có Nginx đứng trước
BindAi gọi được
127.0.0.1Chỉ process trên cùng máy (Nginx cùng VM)
10.0.1.4Chỉ qua interface có IP đó
0.0.0.0Mọi interface (loopback, private, ...), còn tùy firewall

Bước 3: Xem connection thật khi developer gọi:

ss -tn state established '( sport = :8080 )'
Local 10.0.1.4:8080    Peer 10.0.0.25:51734
Local 10.0.1.4:8080    Peer 10.0.0.25:51736   <-- cùng client, khác source port

Còn order-service gọi Postgres thì chiều ngược lại: order-service là client, source port ephemeral, destination 10.0.2.5:5432.

Bước 4: Test

nc -zv 10.0.1.4 8080
Connection to 10.0.1.4 8080 port [tcp/*] succeeded!

5. Cách hoạt động: TCP 3-way handshake

Laptop 10.0.0.25:51734                 VM 10.0.1.4:8080
        |  ---- SYN (seq=x) -----------------> |
        |  <--- SYN-ACK (seq=y, ack=x+1) ----- |  kernel trả lời, chưa tới Java
        |  ---- ACK (ack=y+1) ---------------> |
        |        ESTABLISHED                    |  vào accept queue
        |                                       |  Tomcat accept() -> xử lý
        |  ---- HTTP GET /orders/123 ---------> |
        |  <--- HTTP 200 JSON ----------------- |
        |  ---- FIN / ACK ... (đóng) ---------> |

6. So sánh TCP và UDP

TCPUDP
Kết nốiCó, handshake trướcKhông, gửi luôn
Đảm bảo tới / đúng thứ tựCó (ACK, retransmit)Không
Flow/congestion controlCóKhông
Overhead / latencyCao hơnThấp
Dùng choHTTP/1.1, HTTP/2, JDBC Postgres, SSH, KafkaDNS (phần lớn), video/voice, game, QUIC/HTTP/3
JavaSocket, ServerSocketDatagramSocket

7. Khi nào dùng

Vậy 1 server port 8080 có phải chỉ nhận được 65535 connection không?

Không, đây là hiểu lầm phổ biến. Giới hạn 65535 là của source port trên một client tới cùng một đích. Server phân biệt connection bằng cả 4-tuple, nên nhiều client khác IP/port đều vào chung 8080 được. Giới hạn thực tế ở server là file descriptor (ulimit -n), RAM, và số thread của Tomcat.

Trong Docker, mình EXPOSE 8080 rồi mà máy host vẫn không gọi được?

Đúng, EXPOSE chỉ là tài liệu. Port 8080 trong container và port 8080 trên host là hai thứ khác nhau. Phải map:

docker run -p 8080:8080 order-service
#            host:container

Và bên trong container app phải listen 0.0.0.0. Nếu listen 127.0.0.1 thì đó là loopback của container, port mapping cũng không vào được.

Phỏng vấn hỏi về TCP/UDP và port thì trả lời sao?

Q1. TCP khác UDP thế nào?

🇻🇳 Tiếng Việt:

TCP là connection-oriented: bắt tay 3 bước, đảm bảo dữ liệu tới đủ, đúng thứ tự, có flow và congestion control. UDP không kết nối, không đảm bảo, nhưng nhẹ và latency thấp. HTTP/1.1, HTTP/2, JDBC dùng TCP; DNS, streaming, HTTP/3 (qua QUIC) dùng UDP.

🇬🇧 English:

TCP is connection-oriented: it uses a three-way handshake and guarantees reliable, ordered delivery with flow and congestion control. UDP is connectionless with no delivery guarantee, but it is lightweight and low latency. HTTP/1.1, HTTP/2 and JDBC use TCP; DNS, media streaming and HTTP/3 over QUIC use UDP.

Q2. Mô tả TCP 3-way handshake.

🇻🇳 Tiếng Việt:

Client gửi SYN, server trả SYN-ACK, client gửi ACK. Sau đó connection ESTABLISHED và nằm trong accept queue chờ ứng dụng accept. Nếu port không có ai listen, server trả RST, client thấy connection refused.

🇬🇧 English:

The client sends SYN, the server answers SYN-ACK, and the client sends ACK. The connection is then established and waits in the accept queue until the application accepts it. If nothing listens on the port, the server replies with RST and the client sees connection refused.

Q3. 0.0.0.0 và 127.0.0.1 khác gì khi bind server?

🇻🇳 Tiếng Việt:

127.0.0.1 chỉ nhận connection từ chính máy đó. 0.0.0.0 nhận trên mọi interface. Khi có Nginx cùng máy, em bind Spring Boot vào 127.0.0.1 để không lộ port 8080.

🇬🇧 English:

127.0.0.1 only accepts connections from the same machine, while 0.0.0.0 listens on all interfaces. When Nginx runs on the same host, I bind Spring Boot to 127.0.0.1 so port 8080 is not exposed.

Cách nhớ ngắn gọn


Tự kiểm tra

Ephemeral port là gì?

Port tạm OS cấp cho phía client khi mở connection ra ngoài, ví dụ 51734 khi gọi tới :8080.

4-tuple gồm những gì?

Source IP, source port, destination IP, destination port.

Lệnh nào xem process nào đang listen port 8080 trên Linux?

sudo ss -ltnp | grep 8080.

Ai trả lời SYN-ACK: kernel hay Tomcat?

Kernel. Tomcat chỉ accept() connection đã hoàn tất handshake.

Vì sao DNS thường dùng UDP?

Câu hỏi/trả lời nhỏ, cần nhanh; không cần handshake. Trả lời lớn thì chuyển sang TCP.