Asio网络库¶
同步通讯¶
客户端¶
- 基本步骤:
- 建立io上下文
- 创建服务端和客户端端口
- 创建套接字socket
- 绑定自定义客户端端口号
- 连接服务端
- 处理服务端响应信息
- 注意事项:
- 客户端可以自定义端口号,也可以由库随机指定
- 示例
#include <boost/asio.hpp>
#include <string>
void client()
{
try
{
//1.建立io上下文
io_service io;
//2.创建服务端和客户端端口
ip::tcp::endpoint epServer(ip::address::from_string("127.0.0.1"), 8888);
ip::tcp::endpoint epClien(ip::tcp::v4(), 6666);
//3.创建socket套接字
ip::tcp::socket socket(io);
//4.绑定客户端端口
socket.open(ip::tcp::v4());
socket.bind(epClien);
//5.连接服务端
socket.connect(epServer);
//6.处理服务端发送来的信息
{
std::array<char, 128> msg = { '\0' };
size_t len = socket.read_some(buffer(msg));
std::cout << "[client]" << "[threadID]=[" << std::this_thread::get_id() << "]" << "服务端响应数据:" << msg.data() << std::endl;
}
}
catch (const std::exception& e)
{
std::cout << "[client]" << e.what() << std::endl;
}
}
服务端¶
- 基本步骤:
- 建立io上下文
- 创建服务端
- 创建接收器
- 创建套接字socket
- 等待客户端连接请求
- 处理服务端响应信息
- 示例
#include <boost/asio.hpp>
#include <string>
void server()
{
try
{
//1.建立io的上下文
io_service io;
//2.创建端口
ip::tcp::endpoint ep(ip::tcp::v4(), 8888);
//3.创建接收器
ip::tcp::acceptor acceptor(io, ep);
while (true)
{
//4.创建socket套接字
ip::tcp::socket socket(io);
//5.等待客户端连接,会阻塞直到有连接到来
acceptor.accept(socket);
//6.添加响应客户端操作
std::string infoRead, infoWrite = "hello, 客户端";
boost::system::error_code ec;
//socket.read_some(buffer(infoRead), ec);
socket.write_some(buffer(infoWrite), ec);
//服务端以完成发送
sentFlag.store(true);
if (ec)
{
std::cout << ec.message() << std::endl;
break;
}
//循环等待下一客户端的连接
}
}
catch (const std::exception& e)
{
std::cout << "[server]" << e.what() << std::endl;
}
}
## 异步通讯
### 服务端
```cpp
#include <boost/asio.hpp>
#include<boost/bind.hpp>
using namespace boost::asio;
//AsyncServer
class AsyncServer
{
private:
ip::tcp::acceptor acceptor;
io_service& io;
public:
AsyncServer(io_service& _io,const ip::tcp::endpoint& _ep):io(_io),acceptor(_io,_ep)
{
start();
}
void start()
{
std::shared_ptr<ip::tcp::socket> socket(new ip::tcp::socket(io));
acceptor.async_accept(*socket, boost::bind(&AsyncServer::accept_handle,this,socket,placeholders::error));
}
void accept_handle(std::shared_ptr<ip::tcp::socket> socket,const boost::system::error_code& ec)
{
if (ec)
return;
socket->async_write_some(buffer("hello, 客户端"), boost::bind(&AsyncServer::write_handle, this, placeholders::error));
start();
}
void write_handle(const boost::system::error_code& ec)
{
std::cout << "send msg complete!" << std::endl;
}
};
测试示例¶
下面示例代码可以在一个进程中模拟客户端服务器收发信息
#include <iostream>
#include <thread>
#include<memory>
#include <boost/asio.hpp>
#include<string>
#include<atomic>
#include<mutex>
std::mutex printMutex;
//线程安全io
#define PRINT(arg) \
{ \
std::lock_guard<std::mutex> lg(printMutex); \
arg \
}
std::atomic<bool> sentFlag = false;//服务端以发送标志
std::atomic<bool> readyFlag(false);//服务端以准备接收客户端标志
using namespace boost::asio;
void server()
{
try
{
//1.建立io的上下文
io_service io;
//2.创建端口
ip::tcp::endpoint ep(ip::tcp::v4(), 8888);
//3.创建接收器
ip::tcp::acceptor acceptor(io, ep);
while (true)
{
//4.创建socket套接字
PRINT(std::cout << "[server]" << "[threadID]=[" << std::this_thread::get_id() << "]" << "已建立服务端ip端口号[" << acceptor.local_endpoint().address() <<" "<< acceptor.local_endpoint().port() <<"]开始监听客户端请求..." << std::endl;)
ip::tcp::socket socket(io);
//服务端以准备接收客户端
readyFlag.store(true);
PRINT(std::cout << "[server]" << "[threadID]=[" << std::this_thread::get_id() << "]开始监听客户端请求..."<<std::endl;)
//5.等待客户端连接,会阻塞直到有连接到来
acceptor.accept(socket);
PRINT(std::cout << "[server]" << "[threadID]=[" << std::this_thread::get_id() << "]" << "已连接客户端口号[" << socket.remote_endpoint().address() << " " << socket.remote_endpoint().port() << "]" << std::endl;)
//6.添加响应客户端操作
std::string infoRead, infoWrite = "hello, 客户端";
boost::system::error_code ec;
//socket.read_some(buffer(infoRead), ec);
socket.write_some(buffer(infoWrite), ec);
//服务端以完成发送
sentFlag.store(true);
if (ec)
{
PRINT(std::cout << ec.message() << std::endl;)
break;
}
//循环等待下一客户端的连接
}
}
catch (const std::exception& e)
{
PRINT(std::cout << "[server]" << e.what() << std::endl;)
}
}
void client()
{
try
{
//1.建立io上下文
io_service io;
//2.创建服务端和客户端端口
ip::tcp::endpoint epServer(ip::address::from_string("127.0.0.1"), 8888);
ip::tcp::endpoint epClien(ip::tcp::v4(), 6666);
//3.创建socket套接字
ip::tcp::socket socket(io);
//4.绑定客户端端口
socket.open(ip::tcp::v4());
socket.bind(epClien);
//等待服务端准备接收连接
while (!readyFlag.load())
{
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
}
//5.连接服务端
socket.connect(epServer);
//PRINT(std::cout << "[client]" << "[threadID]=[" << std::this_thread::get_id() << "]" << "正在连接服务端ip端口号[" << socket.remote_endpoint().address().to_string() << " " << socket.remote_endpoint().port() << "]..." << std::endl;)
PRINT(std::cout << "[client]" << "[threadID]=[" << std::this_thread::get_id() << "]" << "已连接服务端ip端口号[" << socket.remote_endpoint().address().to_string() << " " << socket.remote_endpoint().port() << "]" << std::endl;)
//等待服务端发送完信息
while (!sentFlag.load())
{
PRINT(std::this_thread::sleep_for(std::chrono::milliseconds(100));)
}
//6.处理服务端发送来的信息
{
std::array<char, 128> msg = { '\0' };
size_t len = socket.read_some(buffer(msg));
PRINT(std::cout << "[client]" << "[threadID]=[" << std::this_thread::get_id() << "]" << "服务端响应数据:" << msg.data() << std::endl;)
}
}
catch (const std::exception& e)
{
PRINT(std::cout << "[client]" << e.what() << std::endl;)
}
}
void start()
{
PRINT(std::cout << "************start************" << std::endl;)
std::thread tserver(server);
for (size_t i = 0; i < 1; ++i)
{
client();
}
//因为服务器一直阻塞等待客户端连接,只能强制中止线程,但不到万不得已不使用,因为有些资源不会释放
TerminateThread(tserver.native_handle(),0);
PRINT(std::cout << "*************end************" << std::endl;)
}
int main() {
start();
}