- libev初始化:
#include <ev.h>
struct ev_loop *loop = ev_loop_new(0);
- 创建libev事件循环,根据实际情况选择合适的循环模式(这里0表示默认模式)。
- TCP服务器创建:
- 使用
socket
、bind
、listen
等系统调用创建TCP监听套接字。
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERVER_PORT);
servaddr.sin_addr.s_addr = INADDR_ANY;
bind(listen_fd, (struct sockaddr *)&servaddr, sizeof(servaddr));
listen(listen_fd, BACKLOG);
- 注意设置合适的监听端口(
SERVER_PORT
)和最大连接数(BACKLOG
)。
- 连接接受与类型区分:
- 创建一个
struct ev_io
事件用于监听新连接。
struct ev_io accept_watcher;
ev_io_init(&accept_watcher, accept_cb, listen_fd, EV_READ);
ev_io_start(loop, &accept_watcher);
- 在
accept_cb
回调函数中接受新连接,并通过应用层协议区分短连接和长连接。
void accept_cb(struct ev_loop *loop, struct ev_io *w, int revents) {
int client_fd = accept(listen_fd, NULL, NULL);
char type_buf[1];
recv(client_fd, type_buf, 1, 0);
if (type_buf[0] == 0) {
// 短连接处理逻辑
} else {
// 长连接处理逻辑
}
}
- 短连接事件处理:
struct ev_io short_conn_watcher;
ev_io_init(&short_conn_watcher, short_conn_read_cb, client_fd, EV_READ);
ev_io_start(loop, &short_conn_watcher);
- 在
short_conn_read_cb
回调中读取并处理数据,处理完后关闭连接并停止事件。
void short_conn_read_cb(struct ev_loop *loop, struct ev_io *w, int revents) {
char buf[SHORT_CONN_BUF_SIZE];
int n = recv(w->fd, buf, SHORT_CONN_BUF_SIZE, 0);
if (n > 0) {
// 处理数据
}
close(w->fd);
ev_io_stop(loop, w);
}
- 长连接事件处理:
- 为长连接创建
struct ev_io
读事件和struct ev_timer
心跳定时器事件。
struct ev_io long_conn_watcher;
ev_io_init(&long_conn_watcher, long_conn_read_cb, client_fd, EV_READ);
ev_io_start(loop, &long_conn_watcher);
struct ev_timer heartbeat_timer;
ev_timer_init(&heartbeat_timer, heartbeat_cb, 30.0, 30.0);
ev_timer_start(loop, &heartbeat_timer);
- 在
long_conn_read_cb
中处理长连接数据,在heartbeat_cb
中发送心跳包并处理心跳回应逻辑。
void long_conn_read_cb(struct ev_loop *loop, struct ev_io *w, int revents) {
// 处理长连接数据
}
void heartbeat_cb(struct ev_loop *loop, struct ev_timer *w, int revents) {
// 发送心跳包并处理回应逻辑
}
- 可靠性与安全性实现:
- 数据完整性校验:在发送和接收数据时,计算并验证校验和。例如,发送数据前计算CRC32校验和并附加在数据包末尾,接收端验证CRC32。
- 认证授权:在长连接处理逻辑中,在合适时机(如连接建立后首次数据交互)进行认证授权。
- 加密传输:使用OpenSSL库初始化TLS上下文,在连接建立后进行TLS握手,之后通过TLS加密读写函数进行数据传输。例如:
// 初始化OpenSSL
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_CTX *ctx = SSL_CTX_new(TLSv1_2_server_method());
// 加载证书和私钥
SSL_CTX_use_certificate_file(ctx, "server.crt", SSL_FILETYPE_PEM);
SSL_CTX_use_PrivateKey_file(ctx, "server.key", SSL_FILETYPE_PEM);
// 在连接建立后进行TLS握手
SSL *ssl = SSL_new(ctx);
SSL_set_fd(ssl, client_fd);
SSL_connect(ssl);
- 在数据读写时使用
SSL_read
和SSL_write
代替普通的recv
和send
函数。