Linux:基于TCP Socket的在线翻译

在学习网络编程的过程中,TCP 是绕不开的核心。本篇博客将结合一个**"英译中小词典服务器"项目**,带你从代码角度理解 TCP 编程的基本流程与设计思路(与之前的Udp是差不多的哦,我们主要学习的思路)


一、项目功能概述

我们实现了一个简单的客户端-服务器模型:

  • 客户端:输入英文单词

  • 服务器:查询本地字典并返回中文翻译

  • 通信协议:基于 TCP

例如:

复制代码
客户端输入: apple
服务器返回: 苹果

二、TCP 编程核心流程

1️⃣ 服务端流程

服务端主要分为以下几步:

复制代码
socket -> bind -> listen -> accept -> read/write

对应代码逻辑:

(1)创建 socket

复制代码
_listenSockfd = socket(AF_INET, SOCK_STREAM, 0);
  • AF_INET:IPv4

  • SOCK_STREAM:TCP协议


(2)绑定端口

复制代码
InetAddr local(_port);
bind(_listenSockfd, local.NetAddrPtr(), local.NetAddrLen());

作用:让服务器在某个端口"对外提供服务"。


(3)开始监听

复制代码
listen(_listenSockfd, backlog);
  • backlog 表示等待队列长度

(4)获取连接(关键点)

复制代码
int sockfd = accept(_listenSockfd, CONV(peer), &len);

特点:

  • 阻塞函数

  • 没有客户端连接时会一直等待


(5)通信处理

复制代码
read(sockfd, buffer, sizeof(buffer));
write(sockfd, result.c_str(), result.size());

三、客户端流程

客户端相对简单:

复制代码
socket -> connect -> read/write

(1)创建 socket

复制代码
int sockfd = socket(AF_INET, SOCK_STREAM, 0);

(2)连接服务器

复制代码
connect(sockfd, cilent.NetAddrPtr(), cilent.NetAddrLen());

(3)发送与接收数据

复制代码
write(sockfd, line.c_str(), line.size());
read(sockfd, buffer, sizeof(buffer));

四、模块设计亮点(重点!)

这个项目不仅仅是"能跑",还有几个非常好的设计思想👇


⭐ 1. 解耦设计(函数回调)

复制代码
using func_t = std::function<std::string(const std::string&, InetAddr&)>;

服务器并不关心"业务逻辑",而是通过回调:

复制代码
std::unique_ptr<TcpServer> tsvr = std::make_unique<TcpServer>(
    port,
    [&](const std::string& word, InetAddr& cilent){
        return d.Translate(word, cilent);
    }
);

👉 好处:

  • 可以轻松替换为:

    • 聊天服务器

    • 计算服务

    • 命令执行服务


⭐ 2. 字典模块(Dict)

复制代码
_dict[english] = chinese;

支持格式:

复制代码
apple:苹果
banana:香蕉

查找逻辑:

复制代码
if (_dict.find(word) == _dict.end())
    return "None";

⭐ 3. 封装网络地址(InetAddr)

统一处理:

  • 主机序 → 网络序

  • IP / Port 提取

  • sockaddr 转换

例如:

复制代码
InetAddr addr(peer);
addr.Ip();
addr.Port();

👉 避免重复写底层代码


⭐ 4. 多线程并发处理

复制代码
pthread_create(&tid, nullptr, Routine, td);

每个客户端一个线程:

复制代码
客户端1 ------线程1
客户端2 ------线程2
客户端3 ------线程3

👉 提高并发能力


⭐ 5. 禁止拷贝(工程规范)

复制代码
class NoCopy
{
    NoCopy(const NoCopy&) = delete;
};

用于防止:

  • socket 被误拷贝

  • 资源重复释放


五、三种并发模型对比

1️⃣ 单进程(最简单)

复制代码
Service(sockfd, addr);
  • ❌ 阻塞

  • ❌ 无法并发


2️⃣ 多进程

复制代码
fork();
  • ✅ 稳定

  • ❌ 开销大


3️⃣ 多线程

复制代码
pthread_create(...)
  • ✅ 性能好

  • ✅ 常用方案


六、一个容易忽略的细节(我们之后会解决,这里只是学习代码)

❗ read / write 并不保证完整读写

复制代码
read(sockfd, buffer, sizeof(buffer));

问题:

  • TCP 是流式协议

  • 可能出现:

    • 粘包

    • 半包

👉 工业级方案需要:

  • 自定义协议(长度 + 数据)

  • 或使用分隔符

源代码很多,所以这里就不给啦,详细的可以查看我的gitee目录哦

class_26_3_20/dictionary.txt · 小沐/linux_network - 码云 - 开源中国

相关推荐
电棍2333 分钟前
ubuntu网卡失效
linux
律宏阔7 分钟前
VMware 能识别 USB 设备,但无法连接(灰色)
linux
Rabitebla14 分钟前
【Linux系统编程】指令(三):创建、删除、复制、移动、看内容
linux·数据结构·c++·算法
dog25027 分钟前
写一个时延固定的拥塞控制
网络
AR-26710-30 分钟前
Linux Day9——复习第一部分(实操产出)
linux
PNP Robotics34 分钟前
【PNP具身解读】GPT6 Astra:具身智能新范式,大模型 + Franka机器人快速落地验证一、GPT6 Astra 背后的布局、数据与具身方向
人工智能·学习·机器学习·机器人
一木 之林38 分钟前
手搓家庭服务器:二手装机、Docker部署、端口映射与frp内网穿透
服务器·人工智能·git·编辑器
酣大智1 小时前
华为 VRRP的抢占延迟时间
网络·tcp/ip·vrrp
小李不想当小白1 小时前
PCB结构与组成(PCB设计入门学习笔记)
经验分享·笔记·单片机·嵌入式硬件·学习·pcb工艺·pcb
那年窗外下的雪.1 小时前
第 02 天:Linux 权限、inode、目录项与链接
学习·http