马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
目次
一、引言
二、WebSocket 概念
1. WebSocket 概述
2. WebSocket 协议
WebSocket 握手哀求示例
三、WebSocket 工作原理
四、WebSocket 的实现方式
1. 预备工作
2. WebSocket 服务器实现
服务器代码
3. WebSocket 客户端实现
客户端代码
五、总结
一、引言
在现代互联网应用中,即时通讯、及时数据传输和交互变得越来越重要。传统的 HTTP 协议由于其无状态和哀求/响应模子的限定,难以满意这类需求。WebSocket 协议应运而生,提供了持久的双向通讯通道。本文将深入解析 WebSocket 的概念、工作原理及其在 C++ 中的实现,并联合经典实例进行讲解。
二、WebSocket 概念
1. WebSocket 概述
WebSocket 是一种全双工的通讯协议,设计用于在 Web 浏览器和服务器之间进行及时、低耽误的双向通讯。相较于传统的 HTTP 协议,WebSocket 协议具有以下几个显著特点:
- 持久连接:一旦连接建立,客户端和服务器之间可以连续通讯,避免了频仍的连接建立和关闭过程。
- 低开销:淘汰了 HTTP 哀求/响应头部的开销,得当高频率数据交换。
- 双向通讯:答应客户端和服务器随时发送数据,支持及时应用场景。
2. WebSocket 协议
WebSocket 协议通过 HTTP/1.1 协议进行初始握手,然后升级到 WebSocket 协议。握手乐成后,通讯双方可以通过 TCP 连接进行双向数据传输。
WebSocket 握手哀求示例
- GET /chat HTTP/1.1
- Host: server.example.com
- Upgrade: websocket
- Connection: Upgrade
- Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
- Sec-WebSocket-Version: 13
复制代码 WebSocket 握手响应示例
- HTTP/1.1 101 Switching Protocols
- Upgrade: websocket
- Connection: Upgrade
- Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
复制代码 三、WebSocket 工作原理
WebSocket 的工作流程重要包罗以下几个步骤:
- 建立连接:客户端发起 HTTP 哀求,包含特定的头部字段,用于哀求将连接升级为 WebSocket 协议。
- 协议升级:服务器接收到哀求后,返回相应的头部字段,确认升级为 WebSocket 协议。
- 数据传输:建立 WebSocket 连接后,客户端和服务器可以通过该连接进行双向数据传输,数据帧以二进制或文本格式传输。
- 关闭连接:任意一方可以随时关闭连接。
四、WebSocket 的实现方式
WebSocket 的实现方式可以分为客户端和服务器两部分。在 C++ 中,可以使用开源的 WebSocket 库(如 libwebsockets、Boost.Beast)进行实现。本文将使用 Boost.Asio 和 Boost.Beast 库来实现 WebSocket 客户端和服务器。
1. 预备工作
在开始编写代码之前,请确保已经安装了 Boost 库。可以从 Boost 官方网站下载并安装。
在 Linux 上
在基于 Debian 的体系(如 Ubuntu)上,可以使用以下下令安装 Boost 库:
- sudo apt-get update sudo apt-get install libboost-all-dev
复制代码 在 Windows 上
在 Windows 上,可以使用 vcpkg 或从 Boost 官网下载源码并手动编译安装。以下是使用 vcpkg 的示例:
- 下载并安装 vcpkg。
- 使用 vcpkg 安装 Boost 库:
- vcpkg install boost-asio boost-beast
复制代码 2. WebSocket 服务器实现
服务器代码
- #include <boost/beast/core.hpp>
- #include <boost/beast/websocket.hpp>
- #include <boost/asio/ip/tcp.hpp>
- #include <cstdlib>
- #include <iostream>
- #include <memory>
- #include <string>
- #include <thread>
- namespace beast = boost::beast; // from <boost/beast.hpp>
- namespace http = beast::http; // from <boost/beast/http.hpp>
- namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
- namespace net = boost::asio; // from <boost/asio.hpp>
- using tcp = net::ip::tcp; // from <boost/asio/ip/tcp.hpp>
- // 会话类
- class session : public std::enable_shared_from_this<session> {
- websocket::stream<beast::tcp_stream> ws_;
- beast::flat_buffer buffer_;
- public:
- explicit session(tcp::socket socket)
- : ws_(std::move(socket)) {}
- // 启动异步操作
- void run() {
- // 执行 WebSocket 握手
- ws_.async_accept(beast::bind_front_handler(&session::on_accept, shared_from_this()));
- }
- private:
- // WebSocket 握手的回调函数
- void on_accept(beast::error_code ec) {
- if (ec) {
- std::cerr << "accept: " << ec.message() << std::endl;
- return;
- }
- // 读取消息
- do_read();
- }
- // 读取消息
- void do_read() {
- ws_.async_read(buffer_, beast::bind_front_handler(&session::on_read, shared_from_this()));
- }
- // 读取消息后的回调函数
- void on_read(beast::error_code ec, std::size_t bytes_transferred) {
- if (ec == websocket::error::closed) {
- return;
- }
- if (ec) {
- std::cerr << "read: " << ec.message() << std::endl;
- return;
- }
- std::cout << "Received: " << beast::make_printable(buffer_.data()) << std::endl;
- buffer_.consume(buffer_.size()); // 清空缓冲区
- // 回应消息
- ws_.text(ws_.got_text());
- ws_.async_write(boost::asio::buffer("Echo: Hello from server"), beast::bind_front_handler(&session::on_write, shared_from_this()));
- }
- // 写消息后的回调函数
- void on_write(beast::error_code ec, std::size_t bytes_transferred) {
- if (ec) {
- std::cerr << "write: " << ec.message() << std::endl;
- return;
- }
- // 继续读取消息
- do_read();
- }
- };
- // 监听器类
- class listener : public std::enable_shared_from_this<listener> {
- net::io_context& ioc_;
- tcp::acceptor acceptor_;
- public:
- listener(net::io_context& ioc, tcp::endpoint endpoint)
- : ioc_(ioc), acceptor_(net::make_strand(ioc)) {
- beast::error_code ec;
- // 打开接收器
- acceptor_.open(endpoint.protocol(), ec);
- if (ec) {
- std::cerr << "open: " << ec.message() << std::endl;
- return;
- }
- // 绑定到端点
- acceptor_.bind(endpoint, ec);
- if (ec) {
- std::cerr << "bind: " << ec.message() << std::endl;
- return;
- }
- // 开始监听
- acceptor_.listen(net::socket_base::max_listen_connections, ec);
- if (ec) {
- std::cerr << "listen: " << ec.message() << std::endl;
- return;
- }
- }
- // 启动异步接受操作
- void run() {
- do_accept();
- }
- private:
- // 异步接受操作
- void do_accept() {
- acceptor_.async_accept(net::make_strand(ioc_), beast::bind_front_handler(&listener::on_accept, shared_from_this()));
- }
- // 接受连接后的回调函数
- void on_accept(beast::error_code ec, tcp::socket socket) {
- if (ec) {
- std::cerr << "accept: " << ec.message() << std::endl;
- } else {
- // 创建 WebSocket 会话
- std::make_shared<session>(std::move(socket))->run();
- }
- // 继续接受连接
- do_accept();
- }
- };
- int main(int argc, char* argv[]) {
- try {
- if (argc != 2) {
- std::cerr << "Usage: websocket-server <port>\n";
- return EXIT_FAILURE;
- }
- // 解析命令行参数
- auto const port = static_cast<unsigned short>(std::atoi(argv[1]));
- // 创建 io_context
- net::io_context ioc{1};
- // 创建并启动监听器
- std::make_shared<listener>(ioc, tcp::endpoint{tcp::v4(), port})->run();
- // 运行 io_context
- ioc.run();
- } catch (const std::exception& e) {
- std::cerr << "Error: " << e.what() << std::endl;
- return EXIT_FAILURE;
- }
- return EXIT_SUCCESS;
- }
复制代码 解析:
- session 类:处理惩罚 WebSocket 会话,包罗握手、读写消息等。
- listener 类:负责监听传入的 TCP 连接,并创建新的 WebSocket 会话。
- main 函数:解析下令行参数,创建 io_context,启动监听器并运行。
运行方式: 编译并运行服务器步伐,例如:
在 Linux 上
假设将服务器代码生存为 websocket_server.cpp,使用以下下令进行编译和运行:
- # 编译服务器代码
- g++ -o websocket-server websocket_server.cpp -lboost_system -lboost_thread -lssl -lcrypto -lboost_beast
- # 运行服务器
- ./websocket-server 8080
复制代码 在 Windows 上
假设将服务器代码生存为 websocket_server.cpp,使用以下下令进行编译和运行(需要安装 MinGW):
- # 编译服务器代码
- g++ -o websocket-server websocket_server.cpp -lboost_system -lws2_32 -lssl -lcrypto
- # 运行服务器
- ./websocket-server 8080
复制代码
3. WebSocket 客户端实现
客户端代码
- #include <boost/beast/core.hpp>
- #include <boost/beast/websocket.hpp>
- #include <boost/asio/ip/tcp.hpp>
- #include <cstdlib>
- #include <iostream>
- #include <string>
- namespace beast = boost::beast; // from <boost/beast.hpp>
- namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
- namespace net = boost::asio; // from <boost/asio.hpp>
- using tcp = net::ip::tcp; // from <boost/asio/ip/tcp.hpp>
- int main(int argc, char* argv[]) {
- try {
- if (argc != 3) {
- std::cerr << "Usage: websocket-client <host> <port>\n";
- return EXIT_FAILURE;
- }
- auto const host = argv[1];
- auto const port = argv[2];
- // 创建 io_context
- net::io_context ioc;
- // 解析地址
- tcp::resolver resolver(ioc);
- auto const results = resolver.resolve(host, port);
- // 创建 WebSocket 流
- websocket::stream<tcp::socket> ws{ioc};
- // 连接到服务器
- net::connect(ws.next_layer(), results.begin(), results.end());
- // 执行 WebSocket 握手
- ws.handshake(host, "/");
- // 发送消息
- ws.write(net::buffer(std::string("Hello from client")));
- // 读取响应
- beast::flat_buffer buffer;
- ws.read(buffer);
- std::cout << "Received: " << beast::make_printable(buffer.data()) << std::endl;
- // 关闭 WebSocket 连接
- ws.close(websocket::close_code::normal);
- } catch (const std::exception& e) {
- std::cerr << "Error: " << e.what() << std::endl;
- return EXIT_FAILURE;
- }
- return EXIT_SUCCESS;
- }
复制代码 解析:
- 解析下令行参数:host 和 port。
- 创建 io_context:管理 I/O 操作。
- 解析服务器地址:通过 tcp::resolver。
- 创建 WebSocket 流:通过 websocket::stream<tcp::socket>。
- 连接到服务器:通过 net::connect。
- 执行 WebSocket 握手:通过 ws.handshake。
- 发送消息:通过 ws.write。
- 读取响应:通过 ws.read。
- 关闭 WebSocket 连接:通过 ws.close。
运行方式: 编译并运行客户端步伐,例如:
在 Linux 上
假设将客户端代码生存为 websocket_client.cpp,使用以下下令进行编译和运行:
- # 编译客户端代码
- g++ -o websocket-client websocket_client.cpp -lboost_system -lboost_thread -lssl -lcrypto -lboost_beast
- # 运行客户端
- ./websocket-client localhost 8080
复制代码 在 Windows 上
假设将客户端代码生存为 websocket_client.cpp,使用以下下令进行编译和运行(需要安装 MinGW):
- # 编译客户端代码
- g++ -o websocket-client websocket_client.cpp -lboost_system -lws2_32 -lssl -lcrypto
- # 运行客户端
- ./websocket-client localhost 8080
复制代码
运行结果:
- Received: Echo: Hello from server
复制代码 五、总结
本文深入解析了 WebSocket 的基础概念、工作原理及其在 C++ 中的实现,并联合 Boost.Asio 和 Boost.Beast 库实现了 WebSocket 服务器和客户端。通过详细的示例代码息争析,展示了如何在 C++ 中构建高效、及时的双向通讯应用。希望本文能帮助读者更好地明白和把握 WebSocket 技术及其在 C++ 中的应用,进步网络编程技能。
本文提供的示例代码可以在 Linux 和 Windows 上运行,重要依赖于跨平台的 Boost.Asio 和 Boost.Beast 库。无论您使用哪种操作体系,都需要确保体系上安装了相应的编译器和 Boost 库。通过本文的详细表明和示例,您应该能够在 C++ 环境中实现高效的 WebSocket 客户端和服务器。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |