目录
一、编译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;
}
运行结果