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

3. boost::asio之同步读写的客户端和服务器示例

简介

前面我们介绍了boost::asio同步读写的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 {//创建上下文服务boost::asio::io_context   ioc;//构造endpointtcp::endpoint  remote_ep(boost::asio::ip::make_address("127.0.0.1"), 10086);tcp::socket  sock(ioc);boost::system::error_code   error = boost::asio::error::host_not_found;sock.connect(remote_ep, error);if (error) {cout << "connect failed, code is " << error.value() << " error msg is " << error.message();return 0;}std::cout << "Enter message: ";// 输入消息char request[MAX_LENGTH];std::cin.getline(request, MAX_LENGTH);size_t request_length = strlen(request);// 发送消息boost::asio::write(sock, boost::asio::buffer(request, request_length));// 接受消息char reply[MAX_LENGTH];size_t reply_length = boost::asio::read(sock,boost::asio::buffer(reply, request_length));std::cout << "Reply is: ";std::cout.write(reply, reply_length);std::cout << "\n";}catch (std::exception& e) {std::cerr << "Exception: " << e.what() << endl;}return 0;
}

服务器

session函数

创建session函数,该函数为服务器处理客户端请求,每当我们获取客户端连接后就调用该函数。在session函数里里进行echo方式的读写,所谓echo就是应答式的处理


#include <iostream>
#include <boost/asio.hpp>
#include <memory>using namespace std;
using namespace boost::asio::ip;const int MAX_LENGTH = 1024;
using socket_ptr = std::shared_ptr<boost::asio::ip::tcp::socket>;void session(socket_ptr sock) {try {const int max_length = 1024;for (;;) {char data[max_length];memset(data, '\0', max_length);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 << "connection closed by peer" << endl;break;}else if (error) {throw boost::system::system_error(error);}cout << "receive from " << sock->remote_endpoint().address().to_string() << endl;cout << "receive message is " << data << endl;//回传信息值boost::asio::write(*sock, boost::asio::buffer(data, length));}}catch (std::exception& e) {std::cerr << "Exception in thread: " << e.what() << "\n" << std::endl;}
}

server函数

server函数根据服务器ip和端口创建服务器acceptor用来接收数据,用socket接收新的连接,然后为这个socket创建session。


// day05-SyncServer.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
#include <iostream>
#include <cstdlib>
#include <iostream>
#include <boost/asio.hpp>
#include <set>
using boost::asio::ip::tcp;
const int max_length = 1024;
typedef std::shared_ptr<tcp::socket> socket_ptr;
std::set<std::shared_ptr<std::thread>>  thread_set;
using namespace std;void session(socket_ptr sock) {try {for (;;) {char data[max_length];memset(data, '\0', max_length);boost::system::error_code error;size_t length = sock->read_some(boost::asio::buffer(data, max_length), error);  // 这里不用read的原因是:read要求必须读取指定大小的数据才会返回if (error == boost::asio::error::eof) {std::cout << "connection closed by peer" << endl;break;}else if (error) {throw boost::system::system_error(error);}cout << "receive from " << sock->remote_endpoint().address().to_string() << endl;cout << "receive message is " << data << endl;//回传信息值boost::asio::write(*sock, boost::asio::buffer(data, length));}}catch (std::exception& e) {std::cerr << "Exception in thread: " << e.what() << "\n" << std::endl;}
}void server(boost::asio::io_context& io_context, unsigned short port) {tcp::acceptor a(io_context, tcp::endpoint(tcp::v4(), port));for (;;) {socket_ptr socket(new tcp::socket(io_context));a.accept(*socket);auto t = std::make_shared<std::thread>(session, socket);thread_set.insert(t);  // 加入到集合中,防止一个循环遍历完成之后线程释放}
}int main()
{try {boost::asio::io_context  ioc;server(ioc, 10086);for (auto& t : thread_set) {t->join();}}catch (std::exception& e) {std::cerr << "Exception " << e.what() << "\n";}return 0;
}

同步读写的优劣

1 同步读写的缺陷在于读写是阻塞的,如果客户端对端不发送数据服务器的read操作是阻塞的,这将导致服务器处于阻塞等待状态。
2 可以通过开辟新的线程为新生成的连接处理读写,但是一个进程开辟的线程是有限的,约为2048个线程,在Linux环境可以通过unlimit增加一个进程开辟的线程数,但是线程过多也会导致切换消耗的时间片较多。
3 该服务器和客户端为应答式,实际场景为全双工通信模式,发送和接收要独立分开。
4 该服务器和客户端未考虑粘包处理。
综上所述,是我们这个服务器和客户端存在的问题,为解决上述问题,我们在接下里的文章里做不断完善和改进,主要以异步读写改进上述方案。
当然同步读写的方式也有其优点,比如客户端连接数不多,而且服务器并发性不高的场景,可以使用同步读写的方式。使用同步读写能简化编码难度。

http://www.dtcms.com/a/309833.html

相关文章:

  • 一体化伺服电机在外观检测设备中的应用与优化
  • MyBatis详解
  • 面向对象学习(一)
  • 服务器地域选择指南:深度分析北京/上海/广州节点对网站速度的影响
  • Trice移植(Start with Trice)
  • 网站建设服务器从入门到上手
  • 层次聚类:无需“猜”K值,如何让数据自己画出“家族图谱”?
  • 31. 伪类和伪元素区别
  • PyTorch深度学习快速入门学习总结(四)
  • JS-第十九天-事件(一)
  • safari添加主屏及PWA启动方式
  • 玩转ChatGPT:寻找仪器用户手册
  • TEM在量子点发光材料领域的应用-测试GO
  • 汇川ITS7100E触摸屏交互界面开发(一)调试事项说明
  • BIFU币富探索合规新路径 助力用户玩转RWA
  • 两步走解决家庭路由器无法上网
  • Java 根据多个 MM-dd 日期计算总时长(包含当日和次日)
  • python PIL图片转base64字符串
  • [极客大挑战 2019]RCE ME
  • RockAI 的破壁之战:Yan 架构如何啃下“端侧炼丹”硬骨头?
  • Vue3 setup、ref和reactive函数
  • 元策联盈:深耕金融领域,赋能行业发展​
  • 【Flutter3.8x】flutter从入门到实战基础教程(四):自定义实现一个自增的StatefulWidget组件
  • 磁力搜索+磁力下载!无需解释!直接上车!
  • 工作好用小工具积累
  • EGE 流量开关 LG 518 GSP P11237
  • 异步函数被调用多次,多次处理同一个文件导致占用,如何让异步函数按顺序执行?
  • 书生浦语第五期L0G2
  • 【音视频】WebRTC 中的RTP、RTCP、SDP、Candidate
  • Ubuntu-Server-24.04-LTS版本操作系统如何关闭自动更新,并移除不必要的内核