news 2026/2/25 11:55:07

asio的socket创建与连接的基础实现和与C风格的socket网络通信的对比

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
asio的socket创建与连接的基础实现和与C风格的socket网络通信的对比

asio socket创建与连接的基础实现和与C风格的socket网络通信的对比

一、整体功能概述

基于Boost.Asio库实现了 TCP 网络编程的核心基础操作,涵盖了端点(endpoint)创建TCP 套接字(socket)创建服务端监听器(acceptor)创建与绑定客户端连接(直连 IP / 域名解析)服务端接受连接等关键步骤。

Boost.Asio 是 C++ 的异步 I/O 库,封装了操作系统的网络 API,提供了更优雅的面向对象接口和跨平台能力。


二、代码模块解析

1. 头文件与命名空间
#include<boost/asio.hpp>// Boost.Asio核心头文件#include<iostream>usingnamespaceboost;// 简化boost命名空间使用(实际项目中不建议全局using,易冲突)
  • Boost.Asio 的核心组件都在boost::asio命名空间下,比如io_contextip::tcpsocketacceptor等。
2. 端点(Endpoint)创建:client_end_point&server_end_point

端点是网络通信的地址 + 端口抽象,对应 TCP/IP 的套接字地址结构(如 C 语言的sockaddr_in)。

  • C 语言的sockaddr_in
struct sockaddr_in { unsigned short sin_family; // 协议族,与 socket()函数的第一个参数相同。 unsigned short sin_port; // 16 位端口号,大端序。用 htons(整数的端口)转换。 struct in_addr sin_addr; // IP 地址的结构体。192.168.101.138 unsigned char sin_zero[8]; // 未使用,为了保持与 struct sockaddr 一样的长度而添加。 };
  • Boost.Asio创建 TCP 客户端和服务端端点(endpoint
// 客户端端点(指定具体IP和端口)intclient_end_point(){std::string raw_ip_address="127.4.8.1";unsignedshortport_num=3333;boost::system::error_code ec;// Boost的错误码(替代异常,更灵活)// 解析IP地址(字符串→asio::ip::address对象)asio::ip::address ip_address=asio::ip::make_address(raw_ip_address,ec);if(ec.value()!=0){// 错误处理std::cout<<"Failed to parse the IP address Error code = "<<ec.value()<<".Message is "<<ec.message();returnec.value();}// 创建TCP端点(IP+端口)asio::ip::tcp::endpointep(ip_address,port_num);return0;}// 服务端端点(绑定所有IPv6地址+端口,也可改用v4::any())intserver_end_point(){unsignedshortport_num=3333;asio::ip::address ip_address=asio::ip::address_v6::any();// 通配地址:监听所有网卡asio::ip::tcp::endpointep(ip_address,port_num);return0;}
  • 核心逻辑:将字符串 IP 解析为 Asio 的ip::address对象,再结合端口创建ip::tcp::endpoint(封装了地址和端口的面向对象结构)。
  • 错误处理:使用boost::system::error_code替代异常(也可使用异常,Asio 支持两种方式)。
3. TCP 套接字创建:create_tcp_socket

套接字是网络通信的文件描述符抽象,Asio 用ip::tcp::socket类封装。

intcreate_tcp_socket(){asio::io_context ioc;// Asio的核心:I/O上下文(管理所有I/O操作的事件循环)asio::ip::tcp protocol=asio::ip::tcp::v4();// 指定TCPv4协议asio::ip::tcp::socketsock(ioc);// 创建套接字(关联I/O上下文)boost::system::error_code ec;sock.open(protocol,ec);// 打开套接字(对应C语言的socket()函数)if(ec.value()!=0){std::cout<<"Failed to open the socket! Error code = "<<ec.value()<<".Message is "<<ec.message();returnec.value();}return0;}
  • 关键组件io_context是 Asio 的核心,所有 I/O 操作(如读写、连接、接受)都需要关联到它,它负责调度事件。
  • sock.open():对应 C 语言的socket(AF_INET, SOCK_STREAM, 0)(创建 TCP 套接字)。
4. 服务端监听器(Acceptor)创建:create_acceptor_socket&bind_acceptor_socket

服务端需要用acceptor(监听器)绑定端口并监听连接,Asio 的ip::tcp::acceptor封装了这一逻辑。

// 新版便捷写法:一行完成创建、打开、绑定intcreate_acceptor_socket(){asio::io_context ios;asio::ip::tcp::acceptora(ios,asio::ip::tcp::endpoint(asio::ip::tcp::v4(),3333));return0;}// 老版本:分步实现(打开→绑定)intbind_acceptor_socket(){unsignedshortport_num=3333;asio::ip::tcp::endpointep(asio::ip::address_v4::any(),port_num);asio::io_context ios;asio::ip::tcp::acceptoracceptor(ios,ep.protocol());// 打开协议(TCPv4)boost::system::error_code ec;acceptor.bind(ep,ec);// 绑定端点(对应C语言的bind())if(ec.value()!=0){std::cout<<"Failed to bind the acceptor socket."<<"Error code = "<<ec.value()<<".Message: "<<ec.message();returnec.value();}}
  • acceptor的作用:对应 C 语言的socket() + bind() + listen()组合,Asio 提供了便捷构造函数(直接传入 endpoint,一步完成所有操作)和分步操作(更灵活)两种方式。
  • ip::address_v4::any():对应 C 语言的INADDR_ANY(绑定所有网卡的 IP)。
5. 客户端连接:connect_to_end(直连 IP)&dns_connect_to_end(域名解析)

客户端通过套接字连接服务端端点,Asio 封装了连接和 DNS 解析逻辑。

// 直连IP:同步连接intconnect_to_end(){std::string raw_ip_address="192.168.1.124";unsignedshortport_num=3333;try{asio::ip::tcp::endpointep(asio::ip::make_address(raw_ip_address),port_num);asio::io_context ios;asio::ip::tcp::socketsock(ios,ep.protocol());// 创建套接字sock.connect(ep);// 连接端点(对应C语言的connect())}catch(system::system_error&e){// 异常处理(替代error_code)std::cout<<"Error occured! Error code = "<<e.code()<<".Message: "<<e.what();returne.code().value();}}// 域名解析连接:通过DNS获取IP后连接intdns_connect_to_end(){std::string host="llfc.club";std::string port_num="3333";asio::io_context ios;try{asio::ip::tcp::resolverresolver(ios);// DNS解析器// 解析域名→多个端点(可能是IPv4/IPv6)asio::ip::tcp::resolver::results_type endpoints=resolver.resolve(host,port_num);asio::ip::tcp::socketsock(ios);// 遍历端点并连接(Asio自动处理,直到成功或失败)asio::connect(sock,endpoints);}catch(system::system_error&e){std::cout<<"Error occured! Error code = "<<e.code()<<".Message: "<<e.what();returne.code().value();}}
  • resolver(解析器):对应 C 语言的getaddrinfo()(DNS 解析),Asio 封装了解析过程,返回results_type(多个端点的集合)。
  • asio::connect():自动遍历解析后的端点,尝试连接,直到成功或全部失败(简化了 C 语言中手动遍历addrinfo链表的逻辑)。
6. 服务端接受连接:accept_new_connection

服务端通过acceptor接受客户端的连接请求,得到一个新的套接字用于通信。

intaccept_new_connection(){constintBACKLOG_SIZE=30;// 监听队列大小(对应listen()的backlog参数)unsignedshortport_num=3333;asio::ip::tcp::endpointep(asio::ip::address_v4::any(),port_num);asio::io_context ios;try{asio::ip::tcp::acceptoracceptor(ios,ep.protocol());acceptor.bind(ep);// 绑定端口acceptor.listen(BACKLOG_SIZE);// 开始监听(对应C语言的listen())asio::ip::tcp::socketsock(ios);acceptor.accept(sock);// 阻塞等待连接(对应C语言的accept())// 此时sock是与客户端通信的套接字}catch(system::system_error&e){std::cout<<"Error occured! Error code = "<<e.code()<<".Message: "<<e.what();returne.code().value();}}
  • acceptor.listen(BACKLOG_SIZE):设置监听队列大小,对应 C 语言的listen(sockfd, BACKLOG_SIZE)
  • acceptor.accept(sock):阻塞等待客户端连接,成功后将新的套接字写入sock(对应 C 语言的accept()返回新的文件描述符)。

三、与 C 语言 BSD Socket 的对比

C 语言的 BSD Socket 是过程式的底层 API,直接调用操作系统的系统调用;而 Boost.Asio 是面向对象的封装,基于 C++ 的特性(如类、异常、模板)简化了开发,同时保留了底层功能的灵活性。以下是关键操作的对比:

功能步骤Boost.Asio(C++)实现C 语言 BSD Socket 实现
1. 初始化需创建io_context(I/O 上下文,管理所有 I/O 操作)无需初始化,直接调用系统调用
2. 创建 TCP 套接字asio::ip::tcp::socket sock(ioc); sock.open(tcp::v4());int sockfd = socket(AF_INET, SOCK_STREAM, 0);(返回文件描述符
3. 定义端点 / 地址asio::ip::tcp::endpoint ep(ip::make_address("127.0.0.1"), 3333);(面向对象)手动填充sockaddr_in结构体:
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(3333);
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
4. 服务端绑定端口acceptor.bind(ep);(acceptor 封装了套接字)bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));(需强制类型转换)
5. 服务端监听acceptor.listen(BACKLOG_SIZE);listen(sockfd, BACKLOG_SIZE);
6. 服务端接受连接acceptor.accept(sock);(新连接写入 sock 对象)int clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &addr_len);(返回新文件描述符)
7. 客户端连接sock.connect(ep);(直接传入 endpoint 对象)connect(sockfd, (struct sockaddr*)&addr, sizeof(addr));(需强制类型转换)
8. DNS 域名解析resolver.resolve(host, port);+asio::connect(sock, endpoints);(自动遍历端点)调用getaddrinfo()获取addrinfo链表,手动遍历链表并调用connect(),最后释放freeaddrinfo()
9. 错误处理支持两种方式:
1.boost::system::error_code(返回错误码)
2. 异常捕获(system_error
检查函数返回值(如-1),通过errno获取错误码,调用perror()strerror()查看信息
10. 跨平台自动适配 Windows/Linux/macOS(Asio 封装了不同系统的差异)需处理系统差异:
Windows 需初始化 WSA(WSAStartup()
数据类型差异(如SOCKETvsint
函数名差异(如closesocket()vsclose()
11. 异步操作原生支持异步 I/O(如async_connectasync_acceptasync_read/write),通过回调或协程处理需手动实现(如使用 select/poll/epoll/kqueue,或线程),开发复杂度高

四、核心差异总结

  1. 编程范式

    • C 语言过程式,基于文件描述符(整数)和结构体,手动管理内存和资源,代码冗长且易出错(如强制类型转换、结构体填充、内存释放)。
    • Boost.Asio面向对象,用socketacceptorendpoint等类封装底层操作,隐藏了繁琐的细节(如字节序转换、地址结构体填充)。
  2. 错误处理

    • C 语言:通过返回值(如-1)和errno判断错误,需手动调用perror()strerror()解析错误信息。
    • Boost.Asio:支持错误码error_code)和异常两种方式,错误信息更丰富(包含错误码和描述),且类型安全。
  3. DNS 解析

    • C 语言:需手动调用getaddrinfo(),遍历返回的addrinfo链表,处理每个端点的连接,最后释放资源。
    • Boost.Asio:用resolver自动解析域名,返回results_typeasio::connect()自动遍历端点并连接,简化了代码。
  4. 异步 I/O

    • C 语言:异步操作需手动使用select/epoll/kqueue等 I/O 多路复用技术,或线程池,开发难度大。
    • Boost.Asio:原生支持异步操作(async_*系列函数),通过回调函数、协程(C++20)或future处理结果,是 Asio 的核心优势之一。
  5. 跨平台性

    • C 语言:需处理不同系统的差异(如 Windows 的 WSA 初始化、closesocket()vsclose())。
    • Boost.Asio:封装了系统差异,代码无需修改即可在不同平台运行。

五、注意事项

  1. io_context的作用:Asio 的所有 I/O 操作都依赖io_context,即使是同步操作,也需要创建它(异步操作还需要调用io_context.run()启动事件循环)。
  2. 异常与错误码:代码中同时使用了异常和error_code,Asio 的所有操作都提供了两种重载(带error_code参数的版本不抛异常,不带的版本抛异常),可根据场景选择。
  3. 命名空间:代码中使用using namespace boost;简化代码,但实际项目中建议使用namespace ba = boost::asio;这样的别名,避免命名冲突。
  4. 资源管理:Asio 的类(如socketacceptor)都实现了 RAII(资源获取即初始化),析构时会自动释放资源(如关闭套接字),无需手动调用close()(C 语言需手动关闭文件描述符)。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/21 1:31:55

Hotkey Detective:快速解决Windows热键冲突的实用指南

Hotkey Detective&#xff1a;快速解决Windows热键冲突的实用指南 【免费下载链接】hotkey-detective A small program for investigating stolen hotkeys under Windows 8 项目地址: https://gitcode.com/gh_mirrors/ho/hotkey-detective 你是否遇到过这样的困扰&#…

作者头像 李华
网站建设 2026/2/25 19:26:30

BetterNCM 网易云插件完整安装指南:技术原理与实操方案

BetterNCM 网易云插件完整安装指南&#xff1a;技术原理与实操方案 【免费下载链接】BetterNCM-Installer 一键安装 Better 系软件 项目地址: https://gitcode.com/gh_mirrors/be/BetterNCM-Installer BetterNCM 作为网易云音乐的功能增强插件&#xff0c;通过底层注入技…

作者头像 李华
网站建设 2026/2/16 23:13:50

告别卡顿困扰:智能帧率优化方案深度解析

告别卡顿困扰&#xff1a;智能帧率优化方案深度解析 【免费下载链接】genshin-fps-unlock unlocks the 60 fps cap 项目地址: https://gitcode.com/gh_mirrors/ge/genshin-fps-unlock 你是否曾经在《原神》的激烈战斗中感受到画面卡顿&#xff1f;是否觉得60帧的限制让你…

作者头像 李华
网站建设 2026/2/25 6:32:24

3倍速起飞!Docker镜像构建效率优化实战指南

还在为每次Docker镜像构建等待数十分钟而烦恼&#xff1f;面对复杂项目的多阶段构建&#xff0c;是否常常因缓存失效而重复下载依赖&#xff1f;本文将从问题诊断、工具配置、构建策略到高级技巧&#xff0c;系统解决Docker镜像构建速度瓶颈&#xff0c;让你的CI/CD流水线效率提…

作者头像 李华
网站建设 2026/2/23 11:29:43

Android防撤回神器:告别重要信息丢失的终极解决方案

Android防撤回神器&#xff1a;告别重要信息丢失的终极解决方案 【免费下载链接】Anti-recall Android 免root 防撤回神器 ! 项目地址: https://gitcode.com/gh_mirrors/an/Anti-recall 在日常沟通中&#xff0c;你是否曾经历过这样的场景&#xff1a;工作群里的重要通知…

作者头像 李华