tcp服务器

作者:liuy9615日期:2025/10/9

🧩 一、总体架构思路
TCP 服务器的基本流程:
创建监听套接字 → 绑定 IP 和端口 → 监听端口 → 接受连接 → 通信收发 → 关闭连接
伪代码框架:
int main() {
int listen_fd = socket(AF_INET, SOCK_STREAM, 0); // 创建TCP套接字
bind(listen_fd, …); // 绑定地址和端口
listen(listen_fd, SOMAXCONN); // 开始监听

1while (1) {
2    int client_fd = accept(listen_fd, ...);        // 接受客户端连接
3    handle_client(client_fd);                      // 通信处理
4}
5
6close(listen_fd);
7

}
但这是单线程阻塞模型,无法处理多个客户端。实际项目中,我们需要进一步设计。


⚙️ 二、主要设计模型(从简单到复杂)
1️⃣ 阻塞式单进程/单线程
• 特点:简单、易实现。
• 缺点:一次只能处理一个客户端,效率极低。
• 适用:测试、学习。


2️⃣ 多进程模型
• 每当有客户端连接,就 fork() 一个子进程专门处理该连接。
• 父进程继续监听新的连接。
• 优点:进程隔离稳定,不会因为一个客户端崩溃影响其他。
• 缺点:进程开销大,频繁创建销毁成本高。
示意:
主进程 ——> fork 子进程1 (client1)
——> fork 子进程2 (client2)


3️⃣ 多线程模型
• 主线程负责 accept() 新连接;
• 每个客户端连接由单独线程处理。
• 优点:比多进程轻量,资源共享方便;
• 缺点:线程过多时切换成本高,需考虑线程安全。


4️⃣ I/O 多路复用模型(推荐)
• 使用 select、poll、或更高效的 epoll 来同时管理多个客户端。
• 不为每个连接创建线程,而是通过事件驱动机制处理就绪的套接字。
• 是现代服务器(如 Nginx、Redis)的核心设计方式。
伪代码(以 epoll 为例):
int epfd = epoll_create(1);
epoll_ctl(epfd, EPOLL_CTL_ADD, listen_fd, &event);

while (1) {
int n = epoll_wait(epfd, events, MAX_EVENTS, -1);
for (int i = 0; i < n; ++i) {
if (events[i].data.fd == listen_fd)
accept_new_client(epfd, listen_fd);
else
handle_client_io(events[i].data.fd);
}
}
优点:
• 高并发性能强;
• 无需频繁创建线程;
• 更易管理连接状态。


5️⃣ 线程池 + epoll(生产级推荐)
• 主线程用 epoll 监听事件;
• 一旦某个客户端有数据可读,将任务交给线程池;
• 线程池中的工作线程异步处理任务并返回结果。
优点:
✅ 高性能
✅ 高可扩展性
✅ 控制线程数量
✅ 适合业务逻辑较复杂的应用(如论坛、聊天、数据库代理)


🧠 三、模块化设计思路
一个成熟的 TCP 服务器应分为以下逻辑模块:
模块 功能说明
网络层 (Network) 负责TCP连接、收发数据、心跳检测、断线处理
协议层 (Protocol) 负责数据的编码与解码(如自定义协议或JSON)
业务层 (Logic) 处理注册、登录、发帖、评论等业务逻辑
存储层 (Storage) SQLite / MySQL / 文件系统
线程池 (ThreadPool) 用于并发执行任务
日志模块 (Logger) 记录访问与错误信息
配置模块 (Config) 从配置文件加载IP、端口、数据库信息等


🔌 四、通信协议设计(关键点)
TCP是流式协议,数据没有边界,因此:
• 必须设计数据包格式来区分消息边界。
示例(自定义协议):
[4字节包头: 表示消息长度] [消息体(JSON或二进制)]
解析逻辑:
int len;
recv(sock, &len, 4, 0); // 先收包头
recv(sock, buf, len, 0); // 再收包体


🧱 五、连接管理与状态机
每个客户端连接通常有一个状态:
CONNECTING → AUTHENTICATED → ACTIVE → DISCONNECTED
服务器可用结构体存储每个连接信息:
struct Client {
int fd;
int user_id;
char buffer[1024];
enum { CONNECTED, LOGGED_IN, CLOSED } state;
};


🧰 六、错误处理与健壮性
• 检查系统调用返回值(socket/bind/listen/recv 等)。
• 设置 SO_REUSEADDR,避免端口占用问题。
• 使用 非阻塞 I/O(fcntl 设置 O_NONBLOCK)。
• 加入 超时机制(如心跳包检测)。
• 信号处理(SIGINT 优雅退出、SIGPIPE 忽略)。


📈 七、优化方向(进阶)
优化点 方法
性能 epoll + 非阻塞IO + 线程池
内存 使用对象池或连接池
可靠性 日志系统 + 守护进程重启
安全性 校验输入数据、防止SQL注入、加密传输
可维护性 模块化代码结构,清晰的接口设计


✅ 八、总结
设计层次 关键技术 应用场景
简单学习 阻塞式/多线程 学习TCP通信原理
中等复杂 epoll模型 聊天室、论坛后端
生产环境 epoll + 线程池 + 协议层设计 高并发服务器、RPC框架


tcp服务器》 是转载文章,点击查看原文


相关推荐


Vue3 EffectScope 源码解析与理解
excel2025/10/7

1. 全局变量与基础类定义 activeEffectScope:表示当前正在运行的 effect 作用域。 EffectScope 类:用来管理一组副作用(ReactiveEffect),提供生命周期控制。 import type { ReactiveEffect } from './effect' import { warn } from './warning' // 当前全局正在运行的作用域 export let activeEffectScope: EffectScope | und


Linus 眼中,编程 AI 的真实价值如何?
飞哥数智谈2025/10/6

今天刷到了一段视频,是 Linux 之父 Linus Torvalds 与 VMware 副总裁兼首席开源官 Dirk Hohndel 的一段对话。 内容挺有意思,分享给大家。 主要有两个话题: AI 只是打了鸡血的自动纠错 AI 幻觉带来了 bug 话题是由 Dirk Hohndel 提出,由 Linus Torvalds 进行回答的。 AI 是打了鸡血的自动纠错 针对这一点,Linus Torvalds 认为这一说法有一定的合理性,但 AI 在编程领域的真正潜力是可以成为一个识别“明显愚


从传输层协议到 UDP:轻量高效的传输选择
渡我白衣2025/10/5

前言 在计算机网络中,传输层是一个关键的层级,它为应用进程之间的通信提供了端到端的传输服务。常见的传输层协议有 TCP 和 UDP。前者强调可靠、面向连接的传输,而后者则提供轻量级、无连接的通信方式。传输层位于网络层之上、应用层之下,为进程之间提供端到端的数据传输服务。要理解 UDP 协议,我们需要先了解 传输层的功能与常见协议,再深入探讨为什么 UDP 在今天的网络环境中仍占据着举足轻重的地位。 一、传输层的基本概念 在 OSI 七层模型 和 TCP/IP 五层模型 中,传输层是第四层,它的主


磁盘的理解&&CHS和LBA地址转换
阑梦清川2025/10/3

1.对于磁盘的理解 首先就是我们的操作系统课本上面学习的这个磁盘的基本结构,比如下面的这个磁盘,磁头,磁头臂以及柱面,扇区的相关的概念; 针对于这个部分的内容,我自己也没有什么经验可以分享,因为这个东西就是固定的,唯一需要注意的就是结合图区进行理解,注意分别代表的是我们的图片里面画出来的这个磁盘的那一个具体的部分; 根据上面的内容,我们想要确定扇区只需要 CHS 三个部分即可,C 代表的就是我们的柱面,H 表示的是磁头,S 表示的是扇区,下面的这个是 ima 给出来的具体介绍,不懂就多去问问


2181、合并零之间的节点
Lenyiin2025/10/2

2181、[中等] 合并零之间的节点 1、问题描述: 给你一个链表的头节点 head ,该链表包含由 0 分隔开的一连串整数。链表的 开端 和 末尾 的节点都满足 Node.val == 0 。 对于每两个相邻的 0 ,请你将它们之间的所有节点合并成一个节点,其值是所有已合并节点的值之和。然后将所有 0 移除,修改后的链表不应该含有任何 0 。 返回修改后链表的头节点 head 。 2、代码思路: 跳过第一个节点:链表的开头和结尾都包含值为 0 的节点,我们从第二个节点开始处理(即


【c++】深入理解string类(3):典型OJ题
zzzsde2025/10/2

一 仅仅反转字母 链接如下:https://leetcode-cn.com/problems/reverse-only-letters/submissions/ 思路: 这道题目的核心就是交换,我们发现这个逻辑和当时在数据结构里学的快速排序非常类似:两个指针,一个指向开头,一个指向结尾,如果前一个指针的值小于后面指针的值,就交换。相应的在这道题目:如果前一个指针和后一个指针都是字母,那就交换。 所以我们需要先写一个判断是否是字母的函数。(c语言库中有这个函数,如果记得这个函数的名称和


ASCII 码表
IMPYLH2025/10/2

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是一种字符编码标准,用于表示一组特定的 95 个(英语)可打印字符和 33 个控制字符(共 128 个代码点)。 二进制八进制十进制十六进制字符010 00000403220space (no visible glyph)010 00010413321!010 00100423422"010 00110433523#010 01000443624$010 01


软件设计师软考备战:第五篇 软件工程与项目管理
软考和人工智能学堂10/1/2025

​​软件工程​​是应用系统化、规范化、可量化的方法开发、运行和维护软件的学科。其目标是提高软件质量、降低开发成本、保证开发进度。​​软件危机​​的表现:项目超出预算项目超过计划完成时间软件质量低下软件通常不满足需求项目无法管理,代码难以维护软件工程与项目管理是软件设计师必须掌握的核心知识,不仅关系到软件开发的成功,也直接影响软件质量和项目效益。通过系统学习软件开发全过程和项目管理方法,能够提高软件开发的专业水平和管理能力。​​思考题​。


[wps_clear]wps清理残余 ——注册表不干净
拾贰_Python9/30/2025

WPS卸载后常见的注册表残留位置包括:HKEY_CURRENT_USER和HKEY_LOCAL_MACHINE下的Kingsoft目录、HKEY_CLASSES_ROOT中与WPS相关的条目。此外,HKEY_CLASSES_ROOT\Applications下可能存在wpp.exe相关项,以及HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts.wps等文件关联记录的残留。这些注册表项需要手动清理以实现完全


对《DDD本质论》一文的解读
canonical_entropy2025/10/10

在《DDD本质论:从哲学到数学,再到工程实践的完整指南之理论篇》中,我们建立了一套从第一性原理出发的DDD理论体系。由于原文理论密度较高、概念间关系精微,为帮助读者更清晰地把握其思想脉络,我们设计了一项思想实验,并借助AI进行体系梳理与对比。 我们首先向AI提出以下问题: DDD领域驱动设计的概念有哪些?这些概念之间的相互关系是什么。如果要逐一去掉这些概念,你会按照什么顺序,为什么? 换言之,如果从第一性原理出发,如何逐步推导出这些概念的相互关系? 不要把任何技术看作是一个不可切分的整体,任何

首页编辑器站点地图

Copyright © 2025 聚合阅读

License: CC BY-SA 4.0