Dưới đây là đoạn code mẫu setup dự án nhé (clone từ repo của CodeCrafters.io). Nó là khung của một server TCP kinh điển, bạn có thể dùng để phát triển lên nhiều thứ.
#include <iostream>
#include <cstdlib>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
int main(int argc, char **argv) {
// Flush after every std::cout / std::cerr
std::cout << std::unitbuf;
std::cerr << std::unitbuf;
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0) {
std::cerr << "Failed to create server socket\n";
return 1;
}
// Since the tester restarts your program quite often, setting SO_REUSEADDR
// ensures that we don't run into 'Address already in use' errors
int reuse = 1;
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) {
std::cerr << "setsockopt failed\n";
return 1;
}
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(6379);
if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) {
std::cerr << "Failed to bind to port 6379\n";
return 1;
}
int connection_backlog = 5;
if (listen(server_fd, connection_backlog) != 0) {
std::cerr << "listen failed\n";
return 1;
}
struct sockaddr_in client_addr;
int client_addr_len = sizeof(client_addr);
std::cout << "Waiting for a client to connect...\n";
// You can use print statements as follows for debugging, they'll be visible when running tests.
std::cout << "Logs from your program will appear here!\n";
//
accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len);
std::cout << "Client connected\n";
//
close(server_fd);
return 0;
}
Sau khi dùng code này để có 1 cái sườn cho dự án thì sau khi build và chạy sẽ được
Waiting for a client to connect...
Logs from your program will appear here!
Sau đó bạn mở 1 cái terminal khác lên, nhớ cài redis-cli sau đó gõ lệnh
redis-cli PING
Waiting for a client to connect...
Logs from your program will appear here!
Client connected
Sau đây mình sẽ giải thích ý nghĩa các lệnh theo hướng dễ hiểu nhé
std::cout << std::unitbuf;: Bình thường C++ hay gom chữ lại một cục rồi mới in ra màn hình (buffer). Lệnh này ép nó có chữ nào là in ra ngay lập tức.socket(AF_INET, SOCK_STREAM, 0): Bước đi thuê mặt bằng quán.
AF_INET: Khai báo quán này dùng hệ thống địa chỉ IPv4.SOCK_STREAM: Khai báo quán sẽ dùng giao thức TCP (đảm bảo dữ liệu đến nơi an toàn, đúng thứ tự, không bị rớt mạng giữa chừng). Hệ điều hành sẽ trả về một số nguyên (gọi là File Descriptor) đại diện cho cái socket này, ở đây là server_fd.setsockopt(...) với SO_REUSEADDR: Đây là một trick thực chiến rất hay. Khi cậu tắt server đi bật lại liên tục để debug, hệ điều hành thường vẫn "giữ" cái port đó thêm vài chục giây đề phòng dữ liệu cũ bị kẹt. Nếu bật lại ngay sẽ bị lỗi 'Address already in use'. Dòng này ra lệnh cho hệ điều hành: "Cứ cho tôi dùng lại port này ngay lập tức!".bind)struct sockaddr_in server_addr;: Cậu ghi thông tin địa chỉ quán lên giấy tờ.
INADDR_ANY: Cho phép nhận khách kết nối từ bất kỳ đâu (localhost, mạng LAN, hay Internet).htons(6379): Đăng ký cổng số 6379 (Port mặc định của Redis). Hàm htons chỉ đơn giản là lật ngược thứ tự các byte (Endianness) cho đúng với chuẩn của Network.bind(...): Lệnh này chính thức cầm tờ giấy địa chỉ ở trên gắn vào cái mặt bằng server_fd cậu đã thuê lúc đầu.listen & accept)listen(server_fd, connection_backlog): Quán chính thức mở cửa. Số 5 (backlog) là số lượng "ghế chờ" tối đa ở trước cửa. Nếu có khách đến kết nối mà server cậu đang bận chưa xử lý kịp, họ sẽ được đưa vào hàng đợi. Ai là người thứ 6 tới sẽ bị văng lỗi Connection Refused.accept(...): Lệnh này đóng vai trò như cậu nhân viên đứng đón khách. Nó sẽ chặn (block) chương trình lại, tức là code chạy đến dòng này sẽ đứng im ru, đợi cho đến khi thực sự có một khách hàng (client) kết nối vào. Khi có người vào, thông tin của họ sẽ được ghi lại vào client_addr.close(server_fd): Đóng cái socket lại, trả tài nguyên cho hệ điều hành.Có thể thấy cách một server hoạt động cũng giống như một quán ăn/nhà hàng, đơn giản là thuê mặt bằng → khai thông tin → đăng kí chỗ → mở cửa đón khách.
Nhưng hiện tại “nhà hàng” của chúng ta chỉ có thể đón 1 khách duy nhất. Ở bài tiếp theo chúng ta sẽ xử lí yêu cầu của 1 vị khách hàng này nhé!
Loading comments...