You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Có hai loại socket internet cơ bản: Stream Sockets (SOCK_STREAM) và Datagram Sockets (SOCK_DGRAM).
Stream Sockets là các luồng giao tiếp hai chiều đáng tin cậy, chúng sử dụng một giao thức gọi là TCP (The Transmission Control Protocol), đảm bảo dữ liệu của bạn được truyền đến một cách tuần tự và không có lỗi.
Datagram Sockets, chúng sử dụng giao thức gọi là UDP (User Datagram Protocol), thường được dùng khi ngăn xếp TCP không khả dụng hoặc khi một vài gói tin bị mất không phải là vấn đề nghiêm trọng. À, không đáng tin cậy nhưng tốc độ của nó lại xịn hơn hẳn TCP :))
Linux không coi socket là một file thông thường, nhưng Linux cung cấp một giao diện I/O thống nhất thông qua file descriptor để lập trình viên có thể thao tác với file, socket, pipe, terminal... theo cách tương tự nhau. Đây chính là triết lý nổi tiếng của Unix: "Everything is a file".
Mô hình mạng phân lớp phù hợp với Unix
Application Layer (telnet, ftp, ...)
Host-to-Host Transport Layer (TCP, UDP)
Internet Layer (IP and routing)
Network Access Layer (Ethernet, Wi-fi, ...)
Mã hoá dữ liệu: Một gói dữ liệu được tạo ra, gói dữ liệu được bao bọc trong phần tiêu đề bởi giao thức đầu tiên (ví dụ TFTP), sau đó toàn bộ gói dữ liệu được mã hoá lại bởi giao thức tiếp theo (ví dụ UDP), rồi lại bởi giao thức tiếp theo nữa (ví dụ IP), và cuối cùng là bởi giao thức cuối cùng ở lớp vật lý (ví dụ Ethernet). Khi một máy tính khác nhận được gói dữ liệu, phần cứng sẽ loại bỏ phần tiêu đề Ethernet, nhân hệ điều hành sẽ loại bỏ các tiêu đề IP và UDP, chương trình TFTP sẽ loại bỏ tiêu đề TFTP và cuối cùng máy tính đó sẽ nhận được dữ liệu.
Địa chỉ IP (Internet Protocol Address) là một dãy số dùng để định danh một thiết bị trên mạng Internet hoặc mạng nội bộ. Khi chỉ định một địa chỉ IP, bạn đang xác định thiết bị đích mà bạn muốn gửi dữ liệu đến trên mạng.
IPv4 (số nguyên 32 bit không dấu, mỗi byte được phân tách bởi dấu chấm), địa chỉ loopback 127.0.0.1
IPv6 (số nguyên 128 bit không dấu, mỗi khối hai byte được phân tách bởi dấu hai chấm), địa chỉ loopback ::1
Số cổng là một địa chỉ logic dùng để phân biệt các ứng dụng và dịch vụ mạng khác nhau trên cùng một địa chỉ IP. Khi chỉ định số cổng, bạn đang cho biết ứng dụng hoặc dịch vụ nào trên thiết bị đích mà bạn muốn gửi dữ liệu đến. Các dịch vụ khác nhau trên internet có các số cổng quen thuộc khác nhau, có thể xem chúng trong tệp /etc/services. Các cổng dưới 1024 thường được coi là đặc biệt và thường yêu cầu quyền truy cập đặc biệt của hệ điều hành để sử dụng.
1.2. Thứ tự byte mạng và chuyển đổi địa chỉ IP
TCP/IP định nghĩa một thứ tự byte mạng duy nhất (big-endian) cho bất kỳ mục dữ liệu số nguyên nào chẳng hạn như địa chỉ IP được truyền qua mạng trong tiêu đề gói. Nhưng do thứ tự byte của máy chủ thường là (little-endian) nên Unix cung cấp các hàm sau để chuyển đổi giữa thứ tự byte mạng và thứ tự byte máy chủ:
Cấu trúc sockaddr, lưu trữ thông tin địa chỉ socket một cách tổng quát để các hàm trong API socket sử dụng một cách đồng nhất
structsockaddr {
uint16_tsa_family; // protocol family (AF_INET, AF_INET6, ...)charsa_data[14]; // Address data
};
Cấu trúc sockaddr_in, lưu trữ thông tin địa chỉ cụ thể cho IPv4
structsockaddr_in {
uint16_tsin_family; // protocol family (AF_INET)uint16_tsin_port; // port number in network byte orderstructin_addrsin_addr// IPv4 address in network byte orderunsigned charsin_zero[8] // pad to sizeof(struct sockaddr)
};
Cấu trúc sockaddr_in6, lưu trữ thông tin địa chỉ cụ thể cho IPv6
structsockaddr_in6 {
u_int16_tsin6_family; // protocol family (AF_INET6)u_int16_tsin6_port; // port number in network byte orderu_int32_tsin6_flowinfo; // IPv6 flow informationstructin6_addrsin6_addr; // IPv6 addressu_int32_tsin6_scope_id; // Scope ID
};
Cấu trúc sockaddr_storage, một vùng nhớ đủ lớn để chứa bất kỳ loại địa chỉ của socket nào
structsockaddr_storage {
sa_family_tss_family; // address family// all this is padding, implementation specific, ignore it:char__ss_pad1[_SS_PAD1SIZE];
int64_t__ss_align;
char__ss_pad2[_SS_PAD2SIZE];
};
Kernel sẽ đọc trường sa_family (tương ứng với ss_family) nằm ở đầu vùng nhớ địa chỉ socket, dựa vào giá trị này, kernel xác định dữ liệu đang được lưu trong sockaddr_storage thực chất là địa chỉ IPv4, IPv6 hay một họ địa chỉ khác, sau đó diễn giải các byte còn lại theo cấu trúc tương ứng.
1.4. Các lệnh gọi hệ thống
Hàm socket() được máy khách và máy chủ sử dụng để tạo socket descriptor
Hàm listen() để chuyển sockfd sang trạng thái lắng nghe để có thể chấp nhận các yêu cầu kết nối từ máy khách. Tham số backlog là số lượng yêu cầu kết nối đang chờ xử lý accept() tối đa có thể được phép trước khi hệ điều hành bắt đầu từ chối các yêu cầu.
Hàm connect() sẽ chặn cho đến khi kết nối được thiết lập thành công hoặc xảy ra lỗi. Nếu thành công, bộ mô tả clientfd hiện đã sẵn sàng để đọc và ghi, và kết quả của việc kết nối được đặc trưng bởi cặp socket (x:y, addr.sin_addr:addr.sin_port), trong đó x và y là địa chỉ bên phía máy khách, còn addr.sin_addr và addr.sin_port là địa chỉ bên phía máy chủ.
Hàm accept(), khi ai đó đang cố gằng dùng connect() để kết nối đến máy của bạn trên một cổng mà bạn đang listen(). Kết nối của họ sẽ được xếp vào hàng đợi chờ được accept() xử lý. Nó sẽ trả về cho bạn một bộ socket descriptor hoàn toàn mới để sử dụng cho kết nối duy nhất này. Đột nhiên bạn có hai bộ socket descriptor với giá của một, bộ socket descriptor ban đầu vẫn đang lắng nghe các kết nối mới khác, và bộ socket descriptor mới được tạo cuối cùng đã sẵn sàng để send() và recv().
5 steps of UDP server
- Create UDP socket.
- Bind the socket to server address.
- Wait until datagram packet arrives from client.
- Process the datagram packet and send a reply to client.
- Go back to Step 3.
5 steps of UDP client
- Create UDP socket.
- Send message to server.
- Wait until response from server is recieved.
- Process reply and go back to step 2, if necessary.
- Close socket descriptor and exit.