- 参照:恋恋风尘的官方博客
- 讲解:C++ asio网络编程
- 笔记下载地址:gitee:笔记/c++/网络编程/asio
网络编程基本流程
网络编程的基本流程对于服务端是这样的
-
服务端
- socket——创建socket对象。
- bind——绑定本机ip+port。
- listen——监听来电,若在监听到来电,则建立起连接。
- accept——再创建一个socket对象给其收发消息。原因是现实中服务端都是面对多个客户端,那么为了区分各个客户端,则每个客户端都需再分配一个socket对象进行收发消息。
- read、write——就是收发消息了。
-
客户端
- socket——创建socket对象。
- connect——根据服务端ip+port,发起连接请求。
- write、read——建立连接后,就可发收消息了。
-
如下图
TCP网络编程
终端节点创建
- 所谓终端节点就是用来通信的端对端的节点,可以通过ip地址和端口构造,其的节点可以连接这个终端节点做通信.
#include "boost/asio.hpp"
服务端(server)节点创建
- 通过ipv6连接
int server_end_point()
{
unsigned short port_num = 3333;
boost::asio::ip::address ip_address = boost::asio::ip::address_v6::any();
boost::asio::ip::tcp::endpoint ep(ip_address, port_num);
return 0;
}
客户端(client)节点创建
int client_end_point() {
//ip地址
std::string raw_ip_address = "127.4.8.1";
//端口号
unsigned short port_num = 3333;
//错误关键字
boost::system::error_code ec;
//通过服务端的ip地址、端口号获取通信地址
boost::asio::ip::address ip_address = boost::asio::ip::address::from_string(raw_ip_address, ec);
if (ec.value() != 0) {
//有错误
std::cout << "失败,ip.address.Error_code = " << ec.value() << "信息" << ec.message();
return ec.value();
}
//创建连接;地址、端口
boost::asio::ip::tcp::endpoint ep(ip_address, port_num);
return 0;
}
创建socket
服务端端scoket创建
新版创建
- 指定协议,端口连接;
默认实现绑定
int create_acceptor_socket()
{
//上下文(通过上下文服务通信)(旧版本为io_service)
boost::asio::io_context ios;
boost::asio::ip::tcp::acceptor a(
ios,
boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 3333)
);
return 0;
}
旧版创建
int create_acceptor_socket()
{
boost::asio::io_context ios;
boost::asio::ip::tcp::acceptor acceptor(ios);
//老版本需要进行以下操作
//boost::asio::ip::tcp protocol = boost::asio::ip::tcp::v4();
//boost::system::error_code ec;
//acceptor.open(protocol, ec);
//if (ec.value() != 0) {
// std::cout << "失败,ip.address.Error_code = " << ec.value() << "信息" << ec.message();
// return ec.value();
//}
return 0;
}
客户端scoket创建
int create_tcp_socket()
{
//上下文(通过上下文服务通信)(旧版本为io_service)
boost::asio::io_context ioc;
//创建ipv4协议
boost::asio::ip::tcp protocol = boost::asio::ip::tcp::v4();
//创建socket
boost::asio::ip::tcp::socket sock(ioc);
boost::system::error_code ec;
//测试是否成功
sock.open(protocol, ec);
if (ec.value() != 0) {
std::cout << "失败,ip.address.Error_code = " << ec.value() << "信息" << ec.message();
return ec.value();
}
return 0;
}
实现绑定(只有服务端)
- 新版绑定:[[网络编程基本流程介绍#创建socket#新版创建]]
老版本
int bind_acceptor_socket()
{
//省略一部分命名空间,简化以下代码,尽可能少的使用命名空间,防止冲突。
using namespace boost;
unsigned short port_num = 3333;
//生成端点 接收任何地址的连接
asio::ip::tcp::endpoint ep(asio::ip::address_v4::any(), port_num);
//创建服务 确定绑定的服务。
asio::io_context ios;
asio::ip::tcp::acceptor acceptor(ios, ep.protocol());
//手动绑定
boost::system::error_code ec;
acceptor.bind(ep, ec);
//测试
if (ec.value() != 0) {
std::cout << "失败,ip.address.Error_code = " << ec.value() << "信息" << ec.message();
return ec.value();
}
return 0;
}
连接操作(只有客户端)
通过ip地址链接
int connect_to_end()
{
std::string raw_ip_address = "192.169.1.124";
unsigned short port_num = 3333;
try {
boost::asio::ip::tcp::endpoint ep(boost::asio::ip::address::from_string(raw_ip_address),port_num);
boost::asio::io_context ios;
//ep.protocol()确定协议
boost::asio::ip::tcp::socket sock(ios, ep.protocol());
sock.connect(ep);
}
catch (boost::system::system_error& e) {
std::cout << "失败,ip.address.Error_code = " << e.code()<< "信息" << e.what();
return e.code().value();
}
return 0;
}
通过域名链接
int dns_connect_to_end()
{
std::string host = "llfc.club";
std::string port_num = "3333";
boost::asio::io_context ios;
//创建查询器 ,参数列表(域名,端口,官方提供)
boost::asio::ip::tcp::resolver::query resolver_query(host,
port_num,
boost::asio::ip::tcp::resolver::query::numeric_service);
//生成域名解析器,绑定在ios这个上下文服务上
boost::asio::ip::tcp::resolver resolver(ios);
try {
//解析返回迭代器,可以解析到的所有ip
boost::asio::ip::tcp::resolver::iterator it = resolver.resolve(resolver_query);
boost::asio::ip::tcp::socket sock(ios);
boost::asio::connect(sock, it);
}
catch (boost::system::system_error& e) {
std::cout << "失败,ip.address.Error_code = " << e.code() << "信息" << e.what();
return e.code().value();
}
return 0;
}
服务端监听,接收连接
int accept_new_connection()
{
using namespace boost;
//监听队列的大小,(旧版按照tcp算法为:大小 * 2。目前肯定比设定大)
const int BACKLOG_SIZE = 30;
unsigned short port_num = 3333;
//asio::ip::address_v4::any() 接受任何地址
asio::ip::tcp::endpoint ep(asio::ip::address_v4::any(),port_num);
asio::io_context ios;
try {
//生成接收器
asio::ip::tcp::acceptor acceptor(ios,ep.protocol());
//绑定
acceptor.bind(ep);
//监听
acceptor.listen(BACKLOG_SIZE);
//利用scoket与客户端通信
asio::ip::tcp::socket sock(ios);
//接收到的连接交给socket处理
acceptor.accept(sock);
}
catch (system::system_error& e) {
std::cout << "失败,ip.address.Error_code = " << e.code() << "信息" << e.what();
return e.code().value();
}
return 0;
}
标签:asio,socket,ip,流程,编程,网络,tcp,address,boost
From: https://blog.csdn.net/weixin_62612279/article/details/140856787