boost入门(四):Asio实现网络通信

前言

上篇介绍了Asio的简单应用,这篇接着介绍Asio如何实现网络通信。

TCP 通信

服务端同步TCP通信

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#define _CRT_SECURE_NO_WARNINGS
#include <ctime>
#include <iostream>
#include <string>
#include <boost/asio.hpp>

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

//创建返回给客户端的信息
std::string make_daytime_string()
{
using namespace std;
time_t now = time(0);
return ctime(&now);
}

int main()
{
try
{
// 创建I\O执行上下文
boost::asio::io_context io_context;
//创建acceptor来监听新的连接,监听TCP IPV4 13端口
tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), 13));
//循环
for (;;)
{
//创建I\O对象
tcp::socket socket(io_context);
//传给acceptor,让acceptor调用I\O对象的方法
//只有当有新连接时,这个函数才会返回
acceptor.accept(socket);
// 得到回传的数据
std::string message = make_daytime_string();

boost::system::error_code ignored_error;
// 向socket写入回传的数据
boost::asio::write(socket, boost::asio::buffer(message), ignored_error);
}
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}

return 0;
}

客户端同步TCP通信

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>

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

int main()
{
try
{
const char* ip = "127.0.0.1";
//I\O 执行上下文
boost::asio::io_context io_context;
//TCP 解析器
tcp::resolver resolver(io_context);
// 和getaddrinfo相同
tcp::resolver::results_type endpoints =
resolver.resolve(ip, "13");

tcp::socket socket(io_context);
// 连接服务
boost::asio::connect(socket, endpoints);
//循环
for (;;)
{
boost::array<char, 128> buf;
boost::system::error_code error;
//从socket读取信息
size_t len = socket.read_some(boost::asio::buffer(buf), error);

if (error == boost::asio::error::eof)
break; // 连接已被关闭
else if (error)
throw boost::system::system_error(error); // 出现错误
//输出回传的信息
std::cout.write(buf.data(), len);
}
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}

return 0;
}

这两个项目可以进行通信,先运行服务端,然后再运行客户端。

服务端异步TCP通信

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#define _CRT_SECURE_NO_WARNINGS
#include <ctime>
#include <iostream>
#include <string>
#include <boost/bind/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>

using boost::asio::ip::tcp;
//返回当前时间字符串
std::string make_daytime_string()
{
using namespace std;
time_t now = time(0);
return ctime(&now);
}

//enable_shared_from_this保证new_connection对象只要有引用不会被回收
class tcp_connection
: public boost::enable_shared_from_this<tcp_connection>
{
public:
// 共享指针
typedef boost::shared_ptr<tcp_connection> pointer;

static pointer create(boost::asio::io_context& io_context)
{
// 创建I\O socket对象
return pointer(new tcp_connection(io_context));
}
// 返回socket I\O对象
tcp::socket& socket()
{
return socket_;
}
// 处理接收的连接
void start()
{
message_ = make_daytime_string();
// 数据异步写入socket
boost::asio::async_write(socket_, boost::asio::buffer(message_),
// shared_from_this代表当前对象指针
boost::bind(&tcp_connection::handle_write, shared_from_this()
));
}

private:
// 创建socket I\O对象
tcp_connection(boost::asio::io_context& io_context)
: socket_(io_context)
{
}
// 写操作完成后调用的回调函数
void handle_write()
{
}

tcp::socket socket_;
std::string message_;
};

class tcp_server
{
public:
tcp_server(boost::asio::io_context& io_context)
: io_context_(io_context),
acceptor_(io_context, tcp::endpoint(tcp::v4(), 13))
{
// 开启接收
start_accept();
}

private:
void start_accept()
{
// 创建一个套接字
tcp_connection::pointer new_connection =
tcp_connection::create(io_context_);
//I\O 对象调用异步,并绑定回调函数和参数
//此处是监听新连接,新连接一来就会调用回调函数
acceptor_.async_accept(new_connection->socket(),
boost::bind(&tcp_server::handle_accept, this, new_connection,
boost::asio::placeholders::error));
}
//回调处理函数
void handle_accept(tcp_connection::pointer new_connection,
const boost::system::error_code& error)
{
// 接收连接,并处理
if (!error)
{
new_connection->start();
}
// 再次监听
start_accept();
}

boost::asio::io_context& io_context_;// I\O执行上下文
tcp::acceptor acceptor_;//acceptor接收器
};

int main()
{
try
{
// 创建I\O执行上下文
boost::asio::io_context io_context;
// 创建对象实例
tcp_server server(io_context);
// 运行I\O执行上下文的检索函数
io_context.run();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}

return 0;
}

UDP 通信

服务端同步UDP通信

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#define _CRT_SECURE_NO_WARNINGS
#include <ctime>
#include <iostream>
#include <string>
#include <boost/array.hpp>
#include <boost/asio.hpp>

using boost::asio::ip::udp;
// 得到当前时间的字符串
std::string make_daytime_string()
{
using namespace std;
time_t now = time(0);
return ctime(&now);
}

int main()
{
try
{
// I\O执行上下文
boost::asio::io_context io_context;
// 创建I\O对象,监听13号端口UDP协议
udp::socket socket(io_context, udp::endpoint(udp::v4(), 13));

for (;;)
{
boost::array<char, 1> recv_buf;
udp::endpoint remote_endpoint;
// 连接发过去的请求
socket.receive_from(boost::asio::buffer(recv_buf), remote_endpoint);

std::string message = make_daytime_string();

boost::system::error_code ignored_error;
// 将消息发给客户端
socket.send_to(boost::asio::buffer(message),
remote_endpoint, 0, ignored_error);
}
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}

return 0;
}

客户端同步UDP通信

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

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

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

int main(int argc, char* argv[])
{
try
{
const char* ip = "127.0.0.1";
// I\O执行上下文
boost::asio::io_context io_context;

udp::resolver resolver(io_context);
udp::endpoint receiver_endpoint =
*resolver.resolve(udp::v4(), ip, "13").begin();
//I\O对象 socket
udp::socket socket(io_context);
socket.open(udp::v4());

boost::array<char, 1> send_buf = { { 0 } };
//发送信息
socket.send_to(boost::asio::buffer(send_buf), receiver_endpoint);

boost::array<char, 128> recv_buf;
udp::endpoint sender_endpoint;
//接收服务端发送的信息
size_t len = socket.receive_from(
boost::asio::buffer(recv_buf), sender_endpoint);
//打印在控制台中
std::cout.write(recv_buf.data(), len);
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}

return 0;
}

服务端异步UDP通信

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#define _CRT_SECURE_NO_WARNINGS
#include <ctime>
#include <iostream>
#include <string>
#include <boost/array.hpp>
#include <boost/bind/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/asio.hpp>

using boost::asio::ip::udp;
//获取当前时间的字符串
std::string make_daytime_string()
{
using namespace std; // For time_t, time and ctime;
time_t now = time(0);
return ctime(&now);
}

class udp_server
{
public:
udp_server(boost::asio::io_context& io_context)
: socket_(io_context, udp::endpoint(udp::v4(), 13))
{
start_receive();
}

private:
void start_receive()
{
// 异步监听新的请求,请求会让handle_receive回调函数处理
socket_.async_receive_from(
boost::asio::buffer(recv_buffer_), remote_endpoint_,
boost::bind(&udp_server::handle_receive, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
// 处理发送的请求
void handle_receive(const boost::system::error_code& error,
std::size_t /*bytes_transferred*/)
{
if (!error)
{
boost::shared_ptr<std::string> message(
new std::string(make_daytime_string()));
// socket向客户端异步发送信息,发送完之后会调用handle_send回调函数
socket_.async_send_to(boost::asio::buffer(*message), remote_endpoint_,
boost::bind(&udp_server::handle_send, this, message,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
//重新监听新的请求,如果不调用,那么直接不监听新的请求,程序结束
start_receive();
}
}

void handle_send(boost::shared_ptr<std::string> /*message*/,
const boost::system::error_code& /*error*/,
std::size_t /*bytes_transferred*/)
{
}

udp::socket socket_;
udp::endpoint remote_endpoint_;
boost::array<char, 1> recv_buffer_;
};

int main()
{
try
{
// 创建I\O执行上下文
boost::asio::io_context io_context;
// 创建udpService对象
udp_server server(io_context);
// 运行I\O执行上下文函数run
io_context.run();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}

return 0;
}

结尾

以上就是关于Asio对TCP和UDP的简单应用。

评论