当前位置: 首页 > news >正文

嵌入式学习Day33

bs模型与cs模型的区别

**bs模型(Browser/Server模型)cs模型(Client/Server模型)**是两种常见的软件架构模式,它们在结构、部署和维护等方面存在显著差异。以下是两者的主要区别:

架构差异

bs模型基于浏览器作为客户端,所有业务逻辑和数据处理集中在服务器端,客户端仅负责展示和用户交互。典型的bs应用包括网页邮箱、在线办公工具等。

cs模型需要安装独立的客户端软件,客户端承担部分业务逻辑和数据处理,服务器端负责核心数据管理和服务提供。常见的cs应用包括桌面游戏、传统ERP系统等。

部署与维护

bs模型的客户端无需安装,只需浏览器即可访问,升级和维护仅在服务器端完成,降低了用户端的维护成本。

cs模型的客户端需要单独安装和升级,每次更新可能涉及用户端的软件更新,维护成本相对较高。

性能与资源占用

bs模型的性能依赖于网络环境和服务器负载,客户端资源占用较少,适合轻量级应用。

cs模型可以充分利用客户端硬件资源,处理复杂计算和图形渲染时性能更优,适合对性能要求较高的应用

跨平台兼容性

bs模型天然具备跨平台特性,只要设备支持现代浏览器即可运行,兼容性较好。

cs模型通常需要针对不同操作系统开发特定版本,跨平台支持相对复杂。

网络依赖

bs模型高度依赖网络连接,离线状态下功能受限或无法使用。

cs模型部分功能可离线运行,数据同步可在网络恢复后进行。

  1. 性能表现

    • BS资源消耗集中在服务器端 $$ T_{\text{响应}} = T_{\text{网络}} + T_{\text{服务器处理}} $$
    • CS可分担计算到客户端($本地计算 + 数据缓存$)
  2. 安全性

    • CS可采用私有加密协议($AES-256 + 自定义封装$)
    • BS依赖HTTPS等标准安全机制
  3. 典型应用

    • BS:Web邮箱、在线文档
    • CS:大型游戏、专业设计软件

选择依据:

  • 当需要快速迭代、跨平台访问时优先BS
  • 对性能要求高、需要复杂交互时考虑CS

P2P模型概述

P2P(Peer-to-Peer)模型是一种分布式网络架构,节点(peers)直接通信与共享资源,无需依赖中央服务器。其核心特点是去中心化、高扩展性和容错性,广泛应用于文件共享、区块链、实时通信等领域。

关键特点

  1. 去中心化:节点平等参与,无单点故障风险。
  2. 资源共享:节点既是资源提供者(server)又是消费者(client)。
  3. 自组织性:网络动态调整,节点可自由加入或退出。

常见类型

  • 纯P2P:无中心节点,如比特币网络。
  • 混合P2P:部分依赖服务器协调,如Skype。
  • 结构化P2P:使用分布式哈希表(DHT)组织节点,如Chord协议。
  • 非结构化P2P:随机连接节点,如Gnutella。

TCP:

三次握手四次挥手示意图:

TCP三次握手

TCP三次握手是建立连接的过程,确保双方能够正常通信。具体步骤如下:

客户端发送SYN报文,序列号为x,进入SYN_SENT状态。SYN报文表示请求建立连接。

服务器收到SYN报文后,回复SYN+ACK报文,序列号为y,确认号为x+1,进入SYN_RCVD状态。SYN+ACK报文表示确认客户端的请求并同意建立连接。

客户端收到SYN+ACK报文后,发送ACK报文,序列号为x+1,确认号为y+1,进入ESTABLISHED状态。服务器收到ACK报文后也进入ESTABLISHED状态。

客户端 -> 服务器: SYN=1, seq=x
服务器 -> 客户端: SYN=1, ACK=1, seq=y, ack=x+1
客户端 -> 服务器: ACK=1, seq=x+1, ack=y+1

TCP四次挥手

TCP四次挥手是终止连接的过程,确保双方数据完全传输完毕。具体步骤如下:

客户端发送FIN报文,序列号为u,进入FIN_WAIT_1状态。FIN报文表示请求断开连接。

服务器收到FIN报文后,回复ACK报文,确认号为u+1,进入CLOSE_WAIT状态。客户端收到ACK报文后进入FIN_WAIT_2状态。

服务器发送FIN报文,序列号为v,进入LAST_ACK状态。FIN报文表示同意断开连接。

客户端收到FIN报文后,回复ACK报文,确认号为v+1,进入TIME_WAIT状态。服务器收到ACK报文后关闭连接。客户端等待2MSL后也关闭连接。

客户端 -> 服务器: FIN=1, seq=u
服务器 -> 客户端: ACK=1, ack=u+1
服务器 -> 客户端: FIN=1, seq=v
客户端 -> 服务器: ACK=1, ack=v+1

常见问题

三次握手确保双方收发能力正常,避免资源浪费。四次挥手确保数据完全传输,防止数据丢失。TIME_WAIT状态防止最后一个ACK丢失导致服务器无法关闭。

tcp常规流程图:

TCP服务端核心函数解析

在Linux系统中,创建TCP服务端主要涉及以下关键函数,每个函数在通信流程中承担特定角色:

socket()

创建通信端点,返回文件描述符。参数指定协议族和套接字类型:

int socket(int domain, int type, int protocol);
  • domain: 通常为AF_INET(IPv4)或AF_INET6(IPv6)
  • typeSOCK_STREAM表示TCP协议
  • protocol: 通常为0,让系统自动选择

错误时会返回-1,并设置errno。典型用法:

int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {perror("socket creation failed");exit(EXIT_FAILURE);
}

bind()

将套接字与特定IP地址和端口绑定:

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • sockfd: socket()返回的文件描述符
  • addr: 指向包含地址信息的结构体(需转换为sockaddr*
  • addrlen: 地址结构体长度

地址结构体典型配置:

struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 监听所有网卡
servaddr.sin_port = htons(8080); // 端口号

listen()

将套接字置为被动监听状态:

int listen(int sockfd, int backlog);
  • backlog: 已完成连接队列的最大长度,现代内核会自动调整这个值
  • 成功返回0,失败返回-1

典型调用:

if (listen(sockfd, SOMAXCONN) == -1) {perror("listen failed");close(sockfd);exit(EXIT_FAILURE);
}

accept()

接受客户端连接,返回新套接字描述符:

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  • addr: 用于存储客户端地址信息(可设为NULL)
  • addrlen: 输入时为addr缓冲区长度,输出时为实际长度
  • 成功返回非负文件描述符,失败返回-1

recv()/send()

进行数据收发操作:

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
  • flags: 通常为0,可选MSG_WAITALL等标志
  • 返回值表示实际收发字节数,0表示对端关闭连接,-1表示错误

close()

关闭套接字描述符:

int close(int fd);

对于服务端程序,需要分别关闭监听套接字和连接套接字。

服务端示例:

TCP客户端函数解析

在Linux中,TCP客户端通常使用套接字API实现网络通信。以下是TCP客户端中常用函数的详细解析:

socket()

用于创建一个套接字,返回文件描述符。

int socket(int domain, int type, int protocol);
  • domain: 协议族,TCP通常使用AF_INET或AF_INET6
  • type: 套接字类型,TCP使用SOCK_STREAM
  • protocol: 通常为0,系统自动选择
  • 返回值:成功返回非负描述符,失败返回-1

connect()

用于与服务器建立连接。

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • sockfd: socket()返回的描述符
  • addr: 指向包含服务器地址和端口的结构体
  • addrlen: 结构体长度
  • 返回值:成功返回0,失败返回-1

send()

用于向已连接的套接字发送数据。

ssize_t send(int sockfd, const void *buf, size_t len, int flags);
  • sockfd: 已连接的套接字描述符
  • buf: 发送数据缓冲区
  • len: 发送数据长度
  • flags: 通常为0
  • 返回值:成功返回发送的字节数,失败返回-1

recv()

用于从已连接的套接字接收数据。

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
  • sockfd: 已连接的套接字描述符
  • buf: 接收数据缓冲区
  • len: 缓冲区长度
  • flags: 通常为0
  • 返回值:成功返回接收的字节数,0表示连接关闭,-1表示错误

close()

用于关闭套接字并释放资源。

int close(int fd);
  • fd: 要关闭的文件描述符
  • 返回值:成功返回0,失败返回-1

客户端示例:

TCP与UDP的对比

特性TCPUDP
连接方式面向连接无连接
可靠性可靠传输尽最大努力交付
数据顺序保证顺序不保证顺序
流量控制滑动窗口机制
头部开销20字节(最小)8字节
适用场景文件传输、Web浏览视频流、DNS查询

TCP粘包问题概述

在Linux网络编程中,TCP粘包是指发送方多次发送的数据被接收方一次性接收的现象,导致数据边界模糊。TCP是字节流协议,本身没有"包"的概念,数据被视为连续的字节流,因此需要应用层自行处理消息边界。

粘包产生原因

发送方和接收方缓冲区机制可能导致粘包:

  • 发送方Nagle算法合并小数据包
  • 接收方缓冲区数据堆积后一次性读取
  • 网络传输延迟导致多个数据包同时到达

解决方案

固定长度法 发送方和接收方约定固定长度的消息,不足部分填充。

特殊字符分隔法 使用特殊字符(如\n)作为消息边界,适用于文本协议。

长度前缀法 在消息头添加长度字段,接收方先读长度再读内容。最常用的可靠方案。

注意事项

  • UDP不存在粘包问题,因其保留消息边界
  • 异步/非阻塞IO场景需配合状态机处理半包情况
  • 网络字节序转换需使用htonl/ntohl等函数保证跨平台兼容性
http://www.xdnf.cn/news/882109.html

相关文章:

  • 如何更快的提升项目的开发进度
  • 从 ClickHouse、Druid、Kylin 到 Doris:网易云音乐 PB 级实时分析平台降本增效
  • 【SSM】SpringBoot笔记2:整合Junit、MyBatis
  • XHR / Fetch / Axios 请求的取消请求与请求重试
  • JVM——如何打造一个类加载器?
  • NLP驱动网页数据分类与抽取实战
  • 「深度拆解」Spring Boot如何用DeepSeek重构MCP通信层?从线程模型到分布式推理的架构进化
  • 自动驾驶+人形机器人?亚马逊即将测试人形机器人送货
  • 元素 “cas:serviceResponse“ 的前缀 “cas“ 未绑定
  • 使用ReactNative加载Svga动画支持三端【Android/IOS/Harmony】
  • StarRocks
  • Spring Boot + OpenAI 构建基于RAG的智能问答系统
  • Java 抗量子算法:构建后量子时代的安全基石
  • 系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
  • 接IT方案编写(PPT/WORD)、业务架构设计、投标任务
  • 为什么要选择VR看房?VR看房有什么优点?
  • 大陆4D毫米波雷达ARS548调试
  • [蓝桥杯]后缀表达式
  • 【图像处理入门】6. 频域图像处理:傅里叶变换与滤波的奥秘
  • 基于protobuf + iceoryx实现共享内存上的零拷贝
  • C++11 尾随返回类型:从入门到精通
  • 3ds Max 渲染技术突破:一键解锁照片级真实感!
  • 【图像处理3D】:世界坐标系
  • MySQL 并发控制和日志
  • c++ 基于openssl MD5用法
  • 【前端】掌握HTML/CSS宽高调整:抓住问题根源,掌握黄金法则
  • 可编辑PPT | 基于大数据中台新能源智能汽车应用解决方案汽车大数据分析与应用解决方案
  • 37.第二阶段x64游戏实战-封包-寻找Socket套接字
  • 基于51单片机的车内防窒息检测报警系统
  • PPT转图片拼贴工具 v4.3