Để code Redis bằng C++ ta cần có một chút kiến thức về các lệnh làm việc với TCP trong C++.
Ta sẽ sử dụng POSIX socket API của C++ để thao tác với phần cứng mạng.
Dưới đây là một số lệnh cần biết:
socket() - Khởi tạo điểm kết nốiĐây là bước đầu tiên để xin hệ điều hành cấp một tài nguyên mạng.
int socket(int domain, int type, int protocol);domain: Thường dùng AF_INET (IPv4) hoặc AF_INET6 (IPv6).type: Với Redis/TCP, ta dùng SOCK_STREAM.protocol: Thường để 0 để OS tự chọn giao thức mặc định (TCP cho SOCK_STREAM).1 thì tèo (lỗi).bind() - Gắn địa chỉ và PortSau khi có "điện thoại" (socket), bạn phải gắn nó với một "số điện thoại" (IP và Port).
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);sockaddr_in để chứa thông tin.
htons(PORT): Chuyển port từ máy bạn (Little-endian) sang Network (Big-endian). Thiếu cái này là Client không tìm thấy đâu!INADDR_ANY: Cho phép server lắng nghe trên tất cả các card mạng của máy.listen() - Chờ đợi kết nốiHàm này biến socket từ trạng thái chủ động (có thể gọi đi) sang thụ động (chờ người khác gọi đến).
int listen(int sockfd, int backlog);backlog là độ dài hàng đợi. Nếu có 100 ông cùng kết nối một lúc mà bạn để backlog là 5, thì những ông sau sẽ bị báo "Connection Refused" trong khi bạn chưa kịp accept.accept() - Chấp nhận "cuộc gọi"Đây là hàm Blocking. Chương trình sẽ dừng ở đây cho đến khi có một Client kết nối tới.
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);sockfd cũ: Tiếp tục để listen các khách hàng khác.new_socket mới: Dùng để trò chuyện (send/recv) riêng với khách vừa vào.recv() - Nhận dữ liệu (Lệnh từ Client)Khi Client gửi lệnh như SET name Tuan, dữ liệu sẽ nằm trong Buffer của OS, bạn dùng hàm này để bốc nó ra.
ssize_t recv(int sockfd, void *buf, size_t len, int flags);0, nghĩa là Client đã ngắt kết nối (Graceful shutdown). Nếu trả về 1, có lỗi xảy ra.send() - Phản hồi dữ liệuGửi kết quả thực thi lệnh về cho Client.
ssize_t send(int sockfd, const void *buf, size_t len, int flags);\r\n (ví dụ: +PONG\r\n).Dưới đây là mẫu code cho một TCP server đơn giản
#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
int main() {
// Create socket
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
// Bind to port 8080
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(8080);
bind(server_fd, (struct sockaddr*)&address, sizeof(address));
// Listen for connections
listen(server_fd, 5);
std::cout << "Server listening on port 8080..." << std::endl;
// Accept a connection
struct sockaddr_in client_address;
socklen_t client_len = sizeof(client_address);
int client_fd = accept(server_fd, (struct sockaddr*)&client_address, &client_len);
std::cout << "Client connected!" << std::endl;
// Read data
char buffer[1024] = {0};
recv(client_fd, buffer, (buffer), );
(client_fd, buffer, (buffer), );
}
Loading comments...