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

【C++】在Windows中使用Boost库——实现TCP、UDP通信

目录

一、编译Boost库

 二、TCP服务端

三、TCP客户端

四、UDP连接


一、编译Boost库

1. 先去官网下载Boost库源码

2. 点击下载最新的版本

下载Windows环境的压缩包,然后解压

3. 在解压后的目录路径下找到“bootstrap.bat”

打开控制台,在“bootstrap.bat”的路径下输入

.\bootstrap.bat

执行完成后,就会在当前目录生成一个可执行文件 b2.exe

4. 直接运行“b2.exe”。

编译好后,其默认的安装路径为当前目录下的stage\lib文件夹内

而头文件就在下载当前目录的boost目录里面。

5. 打开VS编辑器并加载工程,点击“项目-》属性”

在“包含目录”中点击“编辑”

添加包含目录如下

在“库目录”中点击“编辑”

添加库目录如下

6. 添加后使用一段测试代码看看是否有报错,能否通过编译

#include<iostream>
#include"boost/asio.hpp"
using namespace std;
using namespace boost;
using asio::ip::tcp;

int main() {
	cout << "server start ……" << endl;
	asio::io_context io;
	tcp::acceptor acptr(io, tcp::endpoint(tcp::v4(), 6688));

	tcp::socket sock(io);
	acptr.accept(sock);
	cout << "client:" << sock.remote_endpoint().address() << endl;
	try {
		while (true) {
			char buf[0xFF];
			sock.receive(asio::buffer(buf));
			sock.send(asio::buffer(buf));
		}
	}
	catch(std::exception& e) {
		cout << e.what();
	}

	sock.close();
	::system("pause");
}

 二、TCP服务端

基于 Boost.Asio 库实现简单 TCP 服务器的代码如下。

实现功能:该服务器可以接受多个客户端的连接,接收客户端发送的数据,并将客户端发送的数据回传给客户端。当客户端断开连接时,服务器会检测到并打印信息。

 头文件(TCPServer_ByBoost.h):

#pragma once
#include <iostream>
#include <boost/asio.hpp>

using boost::asio::ip::tcp;

class TCPServer {
public:
	TCPServer(short port) : acceptor(io_context, tcp::endpoint(tcp::v4(), port)) {
		//初始化acceptor成员变量,acceptor是一个tcp::acceptor类型的对象,它使用io_context和一个tcp::endpoint对象进行初始化。
			//tcp::endpoint对象表示服务器要监听的地址和端口,这里使用tcp::v4()表示 IPv4 地址,端口号由传入的参数port决定。
			//io_context是 Boost.Asio 的输入输出上下文,用于管理异步操作。
		startAccept();  //接受客户端的连接请求
	}

	~TCPServer() {
		io_context.stop();  //停止io_context的运行,以确保所有异步操作都能正确结束。
	}

	void startAccept();
	void handleClient(tcp::socket& socket);

private:
	boost::asio::io_context io_context;
	tcp::acceptor acceptor;
};

源文件(TCPServer_ByBoost.cpp) 

#include "TCPServer_ByBoost.h"

void TCPServer::startAccept() {  //startAccept()用于开始接受客户端连接
		tcp::socket socket(io_context);  //创建一个tcp::socket对象socket,并使用io_context进行初始化。
		acceptor.async_accept(socket, [this, &socket](const boost::system::error_code& error) {  //使用acceptor.async_accept异步接受客户端连接。这个方法会在有客户端连接时调用传入的回调函数。回调函数接受一个boost::system::error_code类型的参数error,用于表示是否有错误发生。
			if (!error) {
				tcp::endpoint clientEndpoint = socket.remote_endpoint();
				std::cout << "Client: " << std::string(clientEndpoint.address().to_string()) + ":" + std::to_string(clientEndpoint.port()) + " connected" << std::endl;  //打印客户端的ip和端口

				std::thread clientThread([this, &socket]() {
					handleClient(socket);
				});
				clientThread.detach();  //使用detach方法将线程分离,使其在后台独立运行,不等待线程结束
			}
			startAccept();
		});
		io_context.run();  //io_context.run()启动io_context的事件循环,处理异步操作
	}

void TCPServer::handleClient(tcp::socket& socket) {  //handleClient()用于处理与单个客户端的通信
		char buffer[1024];
		while (true) {
			boost::system::error_code error;
			tcp::endpoint clientEndpoint = socket.remote_endpoint();
			size_t length = socket.read_some(boost::asio::buffer(buffer), error);  //使用socket.read_some异步读取数据到buffer中。这个方法会在有数据可读时读取一部分数据,并返回读取的字节数。如果发生错误,将错误码存储在error中
			if (error == boost::asio::error::eof) {  //客户端关闭了连接
				std::cout << "Client: " << std::string(clientEndpoint.address().to_string()) + ":" + std::to_string(clientEndpoint.port()) + " closed" << std::endl;
				break;
			}
			else if (error) {  //其它错误
				std::cerr << "Error reading from client: " << error.message() << std::endl;
				break;
			}
			else {
				buffer[length] = '\0';
				std::cout << std::string(clientEndpoint.address().to_string()) + ":" + std::to_string(clientEndpoint.port()) + " Received: " << std::string(buffer) << std::endl;
				boost::asio::write(socket, boost::asio::buffer(buffer, length));
			}
		}
		socket.close();  //关闭与客户端的连接
	}

调用:

#include"TCPServer_ByBoost.h"

int main() {
	try {
		TCPServer server(8888);
	}
	catch (const std::exception& e) {
		std::cerr << "Exception: " << e.what() << std::endl;
	}
	return 0;
}

 运行结果:

三、TCP客户端

基于 Boost.Asio 库实现简单 TCP 客户端的代码如下。

实现功能:客户端定时向服务端发送数据,同时能够异步接收服务端发送来的数据。

头文件(TCPClient_ByBoost.h):

#pragma once
#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread.hpp>

using boost::asio::ip::tcp;

class TCPClient {
public:
	TCPClient(const std::string& serverAddress, short serverPort) : io_context(), socket(io_context) {  //接受服务器地址和端口号作为参数
		tcp::resolver resolver(io_context);  //创建一个tcp::resolver对象,用于解析服务器地址和端口号,得到连接服务器的端点列表
		tcp::resolver::results_type endpoints = resolver.resolve(serverAddress, std::to_string(serverPort));
		boost::asio::connect(socket, endpoints);  //使用boost::asio::connect连接到服务器的其中一个端点
		startReceive();  //开始异步接收服务端数据
	};

	void sendMessage(const std::string& message);  //接受一个字符串参数,表示要发送给服务器的消息
	void startReceive();
private:
	boost::asio::io_context io_context;
	tcp::socket socket;
	boost::asio::streambuf receiveBuffer;
};

源文件(TCPClient_ByBoost.cpp)

#include "TCPClient_ByBoost.h"

void TCPClient::sendMessage(const std::string& message) {  //接受一个std::string类型的参数message,表示要发送给服务器的消息内容。
	boost::asio::write(socket, boost::asio::buffer(message));  //使用boost::asio::write函数将给定的消息写入到客户端的socket中,从而实现向服务器发送消息的功能
};

void TCPClient::startReceive() {
	async_read(socket, receiveBuffer, boost::asio::transfer_at_least(1),  //使用async_read函数异步读取数据,只要接收到至少1个字节的数据就会触发回调
		[this](const boost::system::error_code& error, std::size_t bytes_transferred) {  //回调函数接受两个参数,const boost::system::error_code& error表示是否有错误发生,std::size_t bytes_transferred表示读取的字节数。
		if (!error) {
			std::cout << "Raw buffer content: ";
			std::istreambuf_iterator<char> eos;
			std::string bufferContent(std::istreambuf_iterator<char>(&receiveBuffer), eos);
			std::cout << bufferContent << std::endl;
			startReceive();  // 继续接收下一条消息
		}
		else {
			std::cerr << "Error receiving data: " << error.message() << std::endl;
		}
	});
	boost::thread ioThread([this]() { io_context.run(); });  //创建一个新的线程ioThread,在线程中运行io_context的事件循环。这样可以确保异步读取操作能够在后台持续进行
	ioThread.detach();  //使用detach方法将线程分离,使其在后台独立运行
}

 调用:

#include"TCPClient_ByBoost.h"


int main() {
	try {
		TCPClient client("127.0.0.1", 8888);
		while (true) {
			// 在主线程中定期向服务器发送消息,不会被接收数据阻塞
			client.sendMessage("Hello from client.");
			boost::this_thread::sleep_for(boost::chrono::seconds(5));
		}
	}
	catch (std::exception& e) {
		std::cerr << "Exception: " << e.what() << std::endl;
	}
	return 0;
}

运行结果:

四、UDP连接

基于 Boost.Asio 库实现简单 UDP 连接的代码如下。

实现功能:可以接受多个连接,接收到数据后会将接收的数据回传。

头文件(UDP_ByBoost.h) 

#pragma once

#include <iostream>
#include <boost/asio.hpp>

using boost::asio::ip::udp;

class UDPServer {
public:
	UDPServer(short port) : socket(io_context, udp::endpoint(udp::v4(), port)) {
		startReceive();
	}

	~UDPServer() {
		io_context.stop();
	}

	void startReceive();
	void startSend(std::size_t length);

private:
	boost::asio::io_context io_context;
	udp::socket socket;
	udp::endpoint remote_endpoint;
	char buffer[1024];
};

 源文件(UDP_ByBoost.cpp)

#include "UDP_ByBoost.h"

void UDPServer::startReceive() {
	socket.async_receive_from(boost::asio::buffer(buffer), remote_endpoint,  //socket.async_receive_from异步接收数据。当有数据到达时,回调函数会被调用。
		[this](const boost::system::error_code& error, std::size_t bytes_transferred) {
		if (!error) {
			std::cout << "Received from " << remote_endpoint.address().to_string() << ":" << remote_endpoint.port() << std::endl;
			std::cout << "Received data: " << buffer << std::endl;
			startSend(bytes_transferred);
		}
		else {
			std::cerr << "Error receiving data: " << error.message() << std::endl;
		}
		startReceive();
	});
	io_context.run();
}

void UDPServer::startSend(std::size_t length) {
	socket.async_send_to(boost::asio::buffer(buffer, length), remote_endpoint,  //socket.async_send_to异步发送数据回给客户端。当数据发送完成后,回调函数会被调用。
		[this](const boost::system::error_code& error, std::size_t bytes_sent) {
		if (!error) {
			std::cout << "Sent data back to " << remote_endpoint.address().to_string() << ":" << remote_endpoint.port() << std::endl;
		}
		else {
			std::cerr << "Error sending data: " << error.message() << std::endl;
		}
	});
}

调用: 

#include"UDP_ByBoost.h"


int main() {
	try {
		UDPServer server(12345);
	}
	catch (const std::exception& e) {
		std::cerr << "Exception: " << e.what() << std::endl;
	}
	return 0;
}

运行结果


http://www.kler.cn/news/359995.html

相关文章:

  • Moectf-week1-wp
  • ENSP环回路由的配置
  • 深度学习基础—神经风格迁移
  • PCL 基于中值距离的点云对应关系(永久免费版)
  • 我常用的两个单例模式写法 (继承Mono和不继承Mono的)
  • 通过SSH远端免密登录执行脚本,修改最新5分钟生成文件权限
  • 离散数学 第二讲 特殊集合和集合间关系 笔记 [电子科大]王丽杰
  • uniapp 常用的地区行业各种多选多选,支持回显,复制粘贴可使用
  • 使用HIP和OpenMP卸载的Jacobi求解器
  • Netty笔记
  • 【论文学习与撰写】,论文word文档中出现乱码的情况,文档中显示的乱码,都是英文字母之类的,但打印预览是正常的
  • Flutter 11 Android原生项目集成Flutter Module
  • 判断索引对象中所有元素是否都为真值pandas.Index.all()
  • 【DBA Part01】国产Linux上安装Oracle进行数据迁移
  • opencv 图像缩放操作 - python 实现
  • 【STM32 HAL库】MPU6050姿态解算 卡尔曼滤波
  • vue富文本使用editor
  • Docker 部署 JDK11 图文并茂简单易懂
  • vbs给qq发送消息
  • redis IO多路复用机制