简介
这篇笔记主要记录了boost::asio的socket编程中知识点, 更多的是说明一些坑… 为了简化描述, 这里仅仅针对同步编程时进行描写, 异步编程同理类比即可. 这里仅仅是客户端向服务器发射一条消息, 然后服务器在控制台显示.
客户端
客户端的步骤:
- 创建io_context
- 创建endpoint, 并初始化
- 创建socket, 并连接到指定的endpoint中, 两种连接方式的区别参考: https://stackoverflow.com/questions/15687016/difference-between-socket-connect-and-boostasioconnect
- 向socket写入数据, 有两个方式写入数据,
boost::asio::write
保证可以写完所有数据, 而socket::write_some
只能保证至少写入一个字节, 所以这里用第一个方式.
代码实例:
#include <iostream>
#include <boost/asio.hpp>
#include <string>
std::string raw_ip_addr = "127.0.0.1";
unsigned short port_num = 6769;
int main() {
boost::asio::io_context ioc;
boost::asio::ip::tcp::endpoint
ep(boost::asio::ip::address::from_string(raw_ip_addr), port_num);
boost::asio::ip::tcp::socket sock(ioc, ep.protocol());
sock.connect(ep);
std::string msg("Hello world !\n");
if (boost::asio::write(sock, boost::asio::buffer(msg)) < 0) {
std::cerr << "boost::asio::write() error\n";
return -1;
}
std::cout << "send successfully\n";
return 0;
}
服务器
服务器步骤:
- 创建io_context
- 创建endpoint, 并初始化
- 创建
acceptor
, 作为一个连接器使用 acceptor
绑定到指定的endpoint- 接收socket的连接, 并接收数据
需要格外注意, 即使数据接收成功, 但是如果是没有多余的数据了, 会有eof的错误, 这是提醒数据接收完毕, 需要单独处理, 具体看代码.
代码实例:
#include <iostream>
#include <string>
#include <boost/asio.hpp>
size_t SIZE = 1024;
unsigned short port_num = 6769;
int main() {
boost::asio::io_context ioc;
boost::asio::ip::tcp::endpoint
ep(boost::asio::ip::address_v4::any(), port_num);
boost::asio::ip::tcp::acceptor acceptor(ioc, ep.protocol());
acceptor.bind(ep);
acceptor.listen(5); // 最多排列5个
boost::asio::ip::tcp::socket sock(ioc);
acceptor.accept(sock);
std::string msg;
boost::system::error_code error;
try {
char cmsg[SIZE];
SIZE = boost::asio::read(sock, boost::asio::buffer(cmsg, SIZE), error);
msg += std::string(cmsg, SIZE);
if (error != boost::asio::error::eof) { // 非eof错误, 需要抛出异常
throw boost::system::system_error(error);
}
} catch (std::exception e) {
std::cout << "recv error: " << e.what() << std::endl;
sock.close();
return -1;
}
sock.close();
std::cout << "Message: " << msg << std::endl;
return 0;
}