网站页脚写什么邢台市建设局官方网站
2025/12/28 19:56:36 网站建设 项目流程
网站页脚写什么,邢台市建设局官方网站,建筑网址导航,wordpress asp.net第一部分#xff1a;一个监听fd能管理多少连接#xff1f;1.1 理论极限// 在Linux中#xff0c;一个epoll实例能管理的fd数量取决于#xff1a; // 1. 系统最大文件描述符限制 cat /proc/sys/fs/file-max # 系统总限制#xff08;通常10万-100万#xff09; uli…第一部分一个监听fd能管理多少连接1.1 理论极限// 在Linux中一个epoll实例能管理的fd数量取决于 // 1. 系统最大文件描述符限制 cat /proc/sys/fs/file-max # 系统总限制通常10万-100万 ulimit -n # 单进程限制通常1024-65535 ​ // 2. epoll本身限制实际上没有限制 // epoll使用红黑树管理百万级fd性能依然很好 ​ // 3. 实际影响因素 // - 内存每个fd需要内核和用户空间数据结构 // - CPU事件处理开销 // - 网络带宽和连接数1.2 实际测试数据连接数内存占用CPU使用延迟适用场景1-100 10MB 5%0.1ms小型应用100-100010-50MB5-20%0.5ms中型应用1000-1000050-200MB20-50%1-5ms大型应用10000200MB50%5ms超大规模1.3 Reactor实现限制// 在reactor.c中的限制 #define DEFAULT_MAX_EVENTS 1024 // 每次epoll_wait返回的最大事件数 ​ // 实际可以管理的连接数远大于这个值 // 因为epoll_wait是分批返回的 reactor_t reactor reactor_create(1024, REACTOR_TRIGGER_EDGE); // 这个1024是每次处理的最大事件数不是总连接数限制 ​ // 总连接数受限于 reactor-context_size 1024; // 初始上下文数组大小 // 但会自动扩容 static int ensure_context_capacity(reactor_t reactor, int fd) { if (fd reactor-context_size) { // 自动扩容 int new_size reactor-context_size * 2; // ... } }第二部分数据发送接收的实现细节2.1 Reactor中的数据流// 完整的Reactor数据流示例 static void on_client_read(reactor_t reactor, int fd, reactor_event_t events, void* user_data) { client_context_t* ctx (client_context_t*)user_data; if (events REACTOR_EVENT_READ) { // 1. 接收数据 ssize_t n sock_recv(ctx-sock, ctx-buffer, sizeof(ctx-buffer), 0); if (n 0) { // 2. 处理数据 process_data(ctx, n); // 3. 如果需要回复可以 // a) 立即发送如果数据小 sock_send(ctx-sock, response, response_len, 0); // b) 或改为监视写事件如果数据大或需要异步 reactor_modify(reactor, fd, REACTOR_EVENT_READ | REACTOR_EVENT_WRITE, ctx); } } if (events REACTOR_EVENT_WRITE) { // 发送缓冲区中的数据 send_pending_data(ctx); // 如果发送完成取消写事件监视 if (ctx-send_buffer_empty) { reactor_modify(reactor, fd, REACTOR_EVENT_READ, ctx); } } }2.2 完整的数据处理示例/** * file reactor_data_flow.c * brief Reactor数据流完整示例 */ ​ #include socket.h #include reactor.h #include stdlib.h #include string.h ​ /* 连接上下文 */ typedef struct { socket_t sock; /* 接收缓冲区 */ struct { char data[8192]; size_t len; size_t capacity; } recv_buf; /* 发送缓冲区 */ struct { char data[8192]; size_t len; size_t offset; // 已发送的偏移量 } send_buf; /* 协议状态 */ enum { STATE_READ_HEADER, STATE_READ_BODY, STATE_WRITING } state; size_t expected_size; // 期望接收的数据大小 } connection_t; ​ /** * brief 处理接收到的数据 */ static void process_received_data(connection_t* conn) { /* 简单协议前4字节是长度后面是数据 */ switch (conn-state) { case STATE_READ_HEADER: if (conn-recv_buf.len 4) { // 解析长度 memcpy(conn-expected_size, conn-recv_buf.data, 4); conn-state STATE_READ_BODY; // 移除已处理的头部 memmove(conn-recv_buf.data, conn-recv_buf.data 4, conn-recv_buf.len - 4); conn-recv_buf.len - 4; } break; case STATE_READ_BODY: if (conn-recv_buf.len conn-expected_size) { // 完整数据包到达 char* packet conn-recv_buf.data; // 处理数据包这里简单回显 printf(Received packet: %.*s\n, (int)conn-expected_size, packet); // 准备回复 if (conn-send_buf.len 0) { // 复制到发送缓冲区 memcpy(conn-send_buf.data, packet, conn-expected_size); conn-send_buf.len conn-expected_size; conn-send_buf.offset 0; conn-state STATE_WRITING; } // 移除已处理的数据 memmove(conn-recv_buf.data, conn-recv_buf.data conn-expected_size, conn-recv_buf.len - conn-expected_size); conn-recv_buf.len - conn-expected_size; conn-expected_size 0; conn-state STATE_READ_HEADER; } break; case STATE_WRITING: // 正在发送数据不处理新数据 break; } } ​ /** * brief 发送数据 */ static int send_pending_data(connection_t* conn) { if (conn-send_buf.len 0 || conn-send_buf.offset conn-send_buf.len) { return 0; // 没有数据要发送 } size_t remaining conn-send_buf.len - conn-send_buf.offset; ssize_t sent sock_send(conn-sock, conn-send_buf.data conn-send_buf.offset, remaining, 0); if (sent 0) { conn-send_buf.offset sent; if (conn-send_buf.offset conn-send_buf.len) { // 发送完成 conn-send_buf.len 0; conn-send_buf.offset 0; conn-state STATE_READ_HEADER; return 0; // 发送完成 } return 1; // 还有数据要发送 } return -1; // 发送错误 } ​ /** * brief 客户端事件回调 */ static void on_client_event(reactor_t reactor, int fd, reactor_event_t events, void* user_data) { connection_t* conn (connection_t*)user_data; if (events (REACTOR_EVENT_ERROR | REACTOR_EVENT_HUP)) { // 连接错误或关闭 printf(Client fd%d disconnected\n, fd); reactor_remove(reactor, fd); sock_close(conn-sock); common_free(conn); return; } if (events REACTOR_EVENT_READ) { // 接收数据 size_t available sizeof(conn-recv_buf.data) - conn-recv_buf.len; if (available 0) { ssize_t n sock_recv(conn-sock, conn-recv_buf.data conn-recv_buf.len, available, 0); if (n 0) { conn-recv_buf.len n; // 处理接收到的数据 process_received_data(conn); // 如果有数据要发送添加写事件监视 if (conn-state STATE_WRITING) { reactor_modify(reactor, fd, REACTOR_EVENT_READ | REACTOR_EVENT_WRITE, conn); } } else if (n 0) { // 连接关闭 printf(Client fd%d closed connection\n, fd); reactor_remove(reactor, fd); sock_close(conn-sock); common_free(conn); } } } if (events REACTOR_EVENT_WRITE) { // 发送数据 int result send_pending_data(conn); if (result 0) { // 发送完成取消写事件监视 reactor_modify(reactor, fd, REACTOR_EVENT_READ, conn); } else if (result 0) { // 发送错误 printf(Send error on fd%d\n, fd); reactor_remove(reactor, fd); sock_close(conn-sock); common_free(conn); } // result 1 表示还有数据保持写事件监视 } } ​ /** * brief 接受新连接 */ static void on_accept(reactor_t reactor, int fd, reactor_event_t events, void* user_data) { socket_t server_sock (socket_t)user_data; if (events REACTOR_EVENT_READ) { socket_t client_sock sock_accept(server_sock, NULL, 0); if (client_sock SOCKET_INVALID) { return; } // 设置非阻塞 sock_set_nonblock(client_sock, true); // 创建连接上下文 connection_t* conn common_calloc(1, sizeof(connection_t)); if (!conn) { sock_close(client_sock); return; } conn-sock client_sock; conn-state STATE_READ_HEADER; // 添加到Reactor只监视读事件 if (reactor_add(reactor, client_sock, REACTOR_EVENT_READ, on_client_event, conn) 0) { common_free(conn); sock_close(client_sock); return; } printf(New client connected: fd%d\n, client_sock); } }第三部分性能优化策略3.1 内存池优化/** * brief 连接内存池 * * 避免频繁malloc/free提高性能 */ typedef struct { connection_t* pool; // 连接池 int* free_list; // 空闲列表 int capacity; // 容量 int free_count; // 空闲数量 int used_count; // 使用数量 } connection_pool_t; ​ /** * brief 从内存池分配连接 */ connection_t* connpool_alloc(connection_pool_t* pool) { if (pool-free_count 0) { // 从空闲列表获取 int index pool-free_list[--pool-free_count]; pool-used_count; return pool-pool[index]; } // 扩展池实际实现应支持动态扩容 return NULL; } ​ /** * brief 释放连接到内存池 */ void connpool_free(connection_pool_t* pool, connection_t* conn) { // 计算索引 int index conn - pool-pool; // 重置连接状态 memset(conn, 0, sizeof(connection_t)); // 添加到空闲列表 pool-free_list[pool-free_count] index; pool-used_count--; }3.2 零拷贝优化/** * brief 使用readv/writev进行向量IO * * 减少内存拷贝提高性能 */ #include sys/uio.h ​ static ssize_t receive_with_iovec(connection_t* conn) { struct iovec iov[2]; // 第一个缓冲区接收头部 iov[0].iov_base conn-expected_size; iov[0].iov_len sizeof(conn-expected_size); // 第二个缓冲区接收数据体 iov[1].iov_base conn-recv_buf.data conn-recv_buf.len; iov[1].iov_len conn-recv_buf.capacity - conn-recv_buf.len; ssize_t n readv(conn-sock, iov, 2); if (n 0) { if (n sizeof(conn-expected_size)) { // 收到了完整的头部 conn-recv_buf.len (n - sizeof(conn-expected_size)); } } return n; }3.3 批量事件处理/** * brief 批量处理事件 * * 一次处理多个事件减少系统调用开销 */ static void process_events_batch(reactor_t reactor, int batch_size) { struct epoll_event* events reactor-events; int nfds epoll_wait(reactor-epoll_fd, events, reactor-max_events, -1); // 批量处理 for (int i 0; i nfds; i batch_size) { int count (nfds - i) batch_size ? (nfds - i) : batch_size; // 预处理阶段收集所有事件 for (int j 0; j count; j) { int fd events[i j].data.fd; reactor_event_t ev epoll_to_events(events[i j].events); // 添加到批量处理队列 add_to_batch_queue(fd, ev); } // 批量处理阶段 process_batch_queue(reactor); } }第四部分实际连接数测试4.1 压力测试程序/** * file stress_test.c * brief Reactor压力测试 */ ​ #include socket.h #include reactor.h #include stdio.h #include stdlib.h #include time.h #include pthread.h ​ #define MAX_CLIENTS 10000 #define TEST_DURATION 30 // 测试时长秒 ​ /* 测试统计 */ typedef struct { int total_connections; int current_connections; int failed_connections; size_t total_bytes_received; size_t total_bytes_sent; uint64_t start_time; uint64_t end_time; } test_stats_t; ​ /* 测试客户端 */ typedef struct { socket_t sock; test_stats_t* stats; reactor_t reactor; bool connected; } test_client_t; ​ /** * brief 客户端定时器回调 */ static void on_client_timer(reactor_t reactor, int timer_id, void* user_data) { test_client_t* client (test_client_t*)user_data; if (!client-connected) { // 尝试连接 sock_addr_t addr; sock_addr_ipv4(127.0.0.1, 8080, addr); client-sock sock_create(SOCK_AF_INET, SOCK_TYPE_STREAM); sock_set_nonblock(client-sock, true); if (sock_connect(client-sock, addr, 1000) 0) { client-connected true; client-stats-current_connections; client-stats-total_connections; // 添加到Reactor reactor_add(reactor, client-sock, REACTOR_EVENT_WRITE, NULL, client); } else if (errno ! EINPROGRESS) { client-stats-failed_connections; } } // 发送测试数据 if (client-connected) { char buffer[1024]; snprintf(buffer, sizeof(buffer), Test data from client %d\n, client-sock); ssize_t sent sock_send(client-sock, buffer, strlen(buffer), 100); if (sent 0) { client-stats-total_bytes_sent sent; } else { // 连接可能已断开 client-connected false; client-stats-current_connections--; sock_close(client-sock); } } } ​ /** * brief 运行压力测试 */ void run_stress_test(int client_count) { reactor_t reactor reactor_create(4096, REACTOR_TRIGGER_EDGE); test_stats_t stats {0}; stats.start_time time(NULL); printf(Starting stress test with %d clients...\n, client_count); // 创建测试客户端 test_client_t* clients common_calloc(client_count, sizeof(test_client_t)); for (int i 0; i client_count; i) { clients[i].stats stats; clients[i].reactor reactor; clients[i].connected false; // 每个客户端一个定时器随机间隔发起连接 int interval 100 (rand() % 900); // 100-1000ms reactor_add_timer(reactor, interval, on_client_timer, clients[i], true); } // 运行测试 uint64_t end_time time(NULL) TEST_DURATION; while (time(NULL) end_time) { reactor_run(reactor, 1000); // 每秒打印统计 static uint64_t last_print 0; if (time(NULL) - last_print 1) { printf(Connections: %d/%d (failed: %d) | , stats.current_connections, stats.total_connections, stats.failed_connections); printf(Data: RX%zu TX%zu bytes\n, stats.total_bytes_received, stats.total_bytes_sent); last_print time(NULL); } } stats.end_time time(NULL); // 打印最终结果 printf(\n Stress Test Results \n); printf(Duration: %ld seconds\n, stats.end_time - stats.start_time); printf(Total connections attempted: %d\n, stats.total_connections); printf(Max concurrent connections: %d\n, stats.current_connections); printf(Failed connections: %d\n, stats.failed_connections); printf(Total data sent: %zu bytes\n, stats.total_bytes_sent); printf(Throughput: %.2f connections/sec\n, (double)stats.total_connections / TEST_DURATION); printf(Data rate: %.2f KB/sec\n, (double)stats.total_bytes_sent / TEST_DURATION / 1024); // 清理 for (int i 0; i client_count; i) { if (clients[i].connected) { sock_close(clients[i].sock); } } common_free(clients); reactor_destroy(reactor); }第五部分实际建议5.1 根据需求选择配置// 场景1IM聊天服务器连接多数据少 reactor_t reactor reactor_create(8192, REACTOR_TRIGGER_EDGE); // 使用边沿触发减少事件数量 // 连接数10,000 // 内存每连接~2KB共~20MB ​ // 场景2文件传输服务器连接少数据多 reactor_t reactor reactor_create(1024, REACTOR_TRIGGER_LEVEL); // 使用水平触发确保数据完整传输 // 连接数100-1000 // 缓冲区每连接~64KB ​ // 场景3API网关中等负载 reactor_t reactor reactor_create(4096, REACTOR_TRIGGER_EDGE); // 连接数1000-5000 // 使用连接池复用后端连接5.2 监控和调优// 监控关键指标 void monitor_reactor(reactor_t reactor) { // 1. 连接数 int conn_count reactor_count(reactor); // 2. 事件处理速率 static uint64_t last_events 0; static time_t last_time 0; uint64_t current_events reactor-stats.events_processed; time_t current_time time(NULL); if (current_time last_time) { double events_per_sec (current_events - last_events) / (double)(current_time - last_time); printf(Events/sec: %.2f\n, events_per_sec); last_events current_events; last_time current_time; } // 3. 内存使用 size_t memory_used reactor-context_size * sizeof(event_context_t) reactor-max_events * sizeof(struct epoll_event); printf(Memory used: %.2f MB\n, memory_used / 1024.0 / 1024.0); }总结1.一个监听fd能管理多少个连接理论取决于系统限制Linux上可达10万实际Reactor实现可以轻松管理10,000个并发连接关键使用边沿触发、内存池、批量处理等技术2.数据如何发送接收接收通过REACTOR_EVENT_READ事件触发sock_recv()发送直接调用sock_send()或通过REACTOR_EVENT_WRITE事件异步发送缓冲需要应用层管理发送/接收缓冲区协议需要应用层实现协议解析如长度前缀协议3.性能关键点触发模式边沿触发性能更好缓冲区管理避免频繁分配内存批量处理一次处理多个事件零拷贝使用readv/writev减少内存拷贝Reactor为了实现是生产可用的可以处理数千到数万的并发连接具体取决于硬件配置和应用场景。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询