网站提交入口大全,最近2019中文字幕mv免费看,html在哪里写代码,制作二维码软件Boost.Asio 同步读写及客户端 - 服务器实现详解
参考文献
Boost.Asio 官方文档学习资料来源: 参考网址
一、引言
Boost.Asio作为一个强大的跨平台网络编程库#xff0c;为开发者提供了丰富的网络操作接口。在之前的学习中#xff0c;我们已接触到其同步读写的API函数为开发者提供了丰富的网络操作接口。在之前的学习中我们已接触到其同步读写的API函数本文将在此基础上深入探讨如何运用这些API构建一个完整且能实际运行的客户端与服务器示例且双方均采用阻塞式的同步读写方式来实现通信。
二、客户端设计
设计思路 首要任务是依据服务器的IP地址与端口号构建一个 endpoint这是后续连接的目标定位信息。借助 socket 对象向已确定的 endpoint 发起连接请求尝试与服务器建立通信链路。成功连接后运用同步读写机制实现向服务器发送数据以及接收服务器响应数据的功能。 代码剖析
#include iostream
#include boost/asio.hpp
using namespace std;
using namespace boost::asio::ip;
const int MAX_LENGTH 1024;int main() {try {// 1. 初始化Boost.Asio的核心对象io_context它为后续的网络操作提供运行环境boost::asio::io_context ioc;// 2. 构建远程服务器的endpoint明确通信目标的IP与端口这里以本地回环地址127.0.0.1及端口10086为例tcp::endpoint remote_ep(address::from_string(127.0.0.1), 10086);// 3. 创建用于网络通信的socket对象绑定到之前创建的io_contexttcp::socket sock(ioc);// 4. 向服务器发起连接请求并通过error_code检查连接结果boost::system::error_code error boost::asio::error::host_not_found;sock.connect(remote_ep, error);// 若连接失败输出错误详情并终止程序if (error) {cout 连接失败错误代码: error.value() 错误信息: error.message() endl;return 0;}// 5. 提示用户输入要发送给服务器的消息std::cout 请输入消息: ;char request[MAX_LENGTH];std::cin.getline(request, MAX_LENGTH);// 6. 计算输入消息的长度并通过Boost.Asio的write函数将消息发送至服务器size_t request_length strlen(request);boost::asio::write(sock, boost::asio::buffer(request, request_length));// 7. 准备接收服务器的回复利用read函数从socket读取数据至reply缓冲区char reply[MAX_LENGTH];size_t reply_length boost::asio::read(sock,boost::asio::buffer(reply, request_length));// 8. 输出服务器的回复内容std::cout 服务器回复: ;std::cout.write(reply, reply_length);std::cout \n;}catch (std::exception e) {// 捕获并处理任何可能出现的异常输出错误信息std::cerr 发生异常: e.what() endl;}return 0;
}三、服务器设计
服务器端的设计相对复杂主要由两个关键函数协同完成工作。
session 函数 功能定位此函数专门负责处理单个客户端的连接请求。每当服务器监听到有新客户端接入时便会立即调用该函数对客户端的数据交互进行管理。实现逻辑采用循环结构持续监听客户端发送的数据。一旦接收到数据首先检查错误状态若客户端正常关闭连接函数能及时察觉并结束循环若出现其他错误则抛出异常。对于接收到的有效数据不仅会在服务器端打印出来源客户端的IP地址以及消息内容还会将数据原封不动地回传给客户端实现简单的“echo”功能。代码详情
void session(std::shared_ptrtcp::socket sock) {try {for (;;) {char data[MAX_LENGTH];memset(data, \0, MAX_LENGTH); // 初始化缓冲区确保数据干净// 从客户端socket读取数据同时关注可能出现的错误boost::system::error_code error;size_t length sock-read_some(boost::asio::buffer(data, MAX_LENGTH), error);// 根据不同的错误情况进行相应处理if (error boost::asio::error::eof) {std::cout 连接被客户端关闭 endl;break;} else if (error) {throw boost::system::system_error(error);}// 打印客户端连接信息及发送的消息std::cout 收到来自 sock-remote_endpoint().address().to_string() 的消息 endl;std::cout 消息内容: data endl;// 将接收到的消息原样回传给客户端boost::asio::write(*sock, boost::asio::buffer(data, length));}}catch (std::exception e) {// 捕获并处理线程内出现的异常输出错误详情std::cerr 线程中发生异常: e.what() \n std::endl;}
}server 函数 功能定位作为服务器的启动与管理核心负责创建服务器的监听机制并协调客户端连接的处理流程。实现逻辑首先创建一个 acceptor 对象绑定到指定的IP地址与端口开始监听客户端的连接请求。进入无限循环后每当有新客户端连接到来便创建一个新的 socket 对象用于与该客户端通信并立即启动一个独立的线程在线程中调用 session 函数处理与该客户端的交互同时将线程分离使其能够独立运行避免主线程阻塞。代码详情
void server(boost::asio::io_context io_context, unsigned short port) {// 创建acceptor用于监听指定端口的客户端连接tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), port));for (;;) {// 为新连接创建socket对象std::shared_ptrtcp::socket socket(new tcp::socket(io_context));acceptor.accept(*socket); // 接受客户端连接// 为每个连接创建独立线程处理通信分离线程以独立运行auto t std::make_sharedstd::thread(session, socket);t-detach(); }
}多线程处理优势通过为每个客户端连接分配独立的线程并在其中进行读写操作确保了服务器的 acceptor 能够持续监听新连接不会因某个连接的阻塞读写操作而陷入停滞有效提升了服务器的并发处理能力。
四、同步读写的特性剖析
优点 编程简易性同步读写模式下代码逻辑呈现顺序执行的特点开发者无需处理复杂的异步回调嵌套编写过程清晰明了对于初学者或是处理简单网络场景的项目而言上手难度较低易于快速实现功能。维护便利性由于代码按照线性顺序执行没有异步操作带来的回调函数分散在各处的问题程序的逻辑流易于追踪与理解后续的代码维护与调试工作相对轻松。 缺点 阻塞隐患在服务器端若客户端未能及时发送数据 read 操作将会使线程陷入阻塞状态白白消耗系统资源直到有数据可读为止这在高并发场景下极易引发性能瓶颈。线程资源受限鉴于每个连接都需要独立的线程来维持同步读写操作而操作系统对线程数量存在上限限制例如Linux系统默认2048个线程当连接数大量增加时系统可能无法创建足够的线程导致新连接无法及时处理。线程切换成本大量线程的频繁切换会消耗大量的CPU时间用于上下文保存与恢复使得系统用于实际业务处理的资源被削减整体性能受到负面影响。粘包问题未解决无论是客户端还是服务器端当前的同步读写实现都没有考虑到TCP协议在数据传输过程中可能出现的粘包现象这可能导致接收端无法准确识别消息边界造成数据解析错误。
五、改进方向展望
为克服同步读写的固有缺陷引入异步读写模式成为必然选择
并发性能飞跃异步操作允许在等待数据读写完成的过程中CPU能够转而处理其他任务避免线程阻塞从而能够在相同硬件资源下承载更多的客户端连接大幅提升服务器的并发处理能力。全双工通信优势发送与接收数据的过程相互独立不再受限于同步模式下的先后顺序能够更好地适应复杂多变的通信需求例如实时双向数据交互的场景。粘包处理机制完善可以通过在数据传输中添加特定的消息分隔符或者在数据头部嵌入长度标识符等方式让接收端能够精准地识别每条消息的边界确保数据的完整性与准确性提升系统的可靠性。