C++实现websocket两server两client半双工通信(基于boost!!!)

这篇具有很好参考价值的文章主要介绍了C++实现websocket两server两client半双工通信(基于boost!!!)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  自身环境:ubuntu18.04+gcc7.5.0+boost1.7,3

环境配置

  gcc或者g++一般都有,这里主要介绍一下boost的配置方法
  执行如下代码:

wget https://boostorg.jfrog.io/artifactory/main/release/1.73.0/source/boost_1_73_0.tar.bz2 --no-check-certificate
tar xvf boost_1_73_0.tar.bz2
cd boost_1_73_0
./bootstrap.sh --prefix=/usr 
./b2 
sudo ./b2 install
cat /usr/include/boost/version.hpp | grep "BOOST_LIB_VERSION"

  装完后发现还是会报错:#include <boost/beast/core.hpp> no such file
  这个时候再加一个:

sudo apt-get install libboost-all-dev

  然后编译执行代码就可以了,在这里说明下我不太确定是否要执行那个apt-get,理论上前面是源码编译就没问题了,后面估计是默认库的安装,但是我当时没太注意顺序,两个都做了一下才成功、
boost安装参考:https://blog.csdn.net/HandsomeHong/article/details/128813619

  顺道提一下Linux下查看boost的版本方法:文章来源地址https://www.toymoban.com/news/detail-516899.html

dpkg -S /usr/include/boost/version.hpp

示例源码

客户端——client.h

#ifndef WEBSOCKET_CLIENT_H
#define WEBSOCKET_CLIENT_H
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <string>
#include <thread>
#include <codecvt>
#include <wchar.h>
#include <locale.h>
#include <stdlib.h>

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 = boost::asio::ip::tcp;       // from <boost/asio/ip/tcp.hpp>

class Client {
    public:
        static std::wstring string_to_wstring(const std::string& str);
        static std::string wstring_to_string(const std::wstring& ws);
        static std::string ansi_to_utf8(const std::string& s);
        static std::string utf8_to_ansi(const std::string& s);
        static void connect(std::string IP, const char *port_s);
        static void send(std::string message);
        static void listen(std::string &out);
        static void disconnect();
};
    
#endif

客户端——client.cpp

#include "client.h"

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 = boost::asio::ip::tcp;       // from <boost/asio/ip/tcp.hpp>

net::io_context ioc;
tcp::resolver resolver{ ioc };
websocket::stream<tcp::socket> ws{ ioc };

std::wstring Client::string_to_wstring(const std::string& str) {
    std::wstring r;
    const char *source = str.c_str();
    wchar_t *dest = NULL;
    int len = 0;
    int ret = 0;
    len = strlen(source) + 1;
    if(len <= 1)
        return 0;
    dest = new wchar_t[len];
    ret = mbstowcs(dest, source, len);
    r = std::wstring(dest);
    delete[] dest;
	return r;
}

std::string Client::wstring_to_string(const std::wstring& ws) {
    std::string r = "";
    const wchar_t *source = ws.c_str();
    char *dest = NULL;
    int len = 0;
    int ret = 0;
    len = wcslen(source) + 1;
    if(len <= 1)
        return 0;
    dest = new char[len*sizeof(wchar_t)];
    ret = wcstombs(dest, source, len*sizeof(wchar_t));
    r = std::string(dest);
    delete[] dest;
	return r;
}

std::string Client::ansi_to_utf8(const std::string& s) {
    static std::wstring_convert<std::codecvt_utf8<wchar_t> > conv;
	return conv.to_bytes(string_to_wstring(s));
}

std::string Client::utf8_to_ansi(const std::string& s) {
    static std::wstring_convert<std::codecvt_utf8<wchar_t> > conv;
	return wstring_to_string(conv.from_bytes(s));
}

void Client::connect(std::string IP, const char *port_s) {
	try {
        auto const address = net::ip::make_address(IP); //服务器地址
        auto const port = static_cast<unsigned short>(std::atoi(port_s));//服务器端口号
        tcp::endpoint endpoint{ address, port };
        auto const results = resolver.resolve(endpoint);
        // 在我们从查找中获得的IP地址上建立连接
        net::connect(ws.next_layer(), results.begin(), results.end());
        ws.set_option(websocket::stream_base::decorator(
            [](websocket::request_type& req)
        {
            req.set(http::field::user_agent,
                std::string(BOOST_BEAST_VERSION_STRING) +
                " websocket-client-coro");
        }));
        std::cout << "The port is:" << port_s << std::endl;
        ws.handshake(IP, "/"); //发送握手消息
        std::cout << "The port:" << port_s << " finish!" << std::endl;
    }	
    catch (std::exception const& e)
	{
		std::cerr << "Error: " << e.what() << std::endl;
		return  ;
	}
}

void Client::send(std::string message) {
    while (1) {
        //std::cout << "log:" << message << std::endl;
        ws.write(net::buffer(ansi_to_utf8(message)));
        sleep(1);
    }
}

void Client::listen(std::string &out) {
    while (1) {
        beast::flat_buffer buffer;//创建一个缓冲区用于存放接收到的消息	
	    ws.read(buffer);// 读取一条消息到缓冲区
	    out = beast::buffers_to_string(buffer.cdata());
	    //std::cout << utf8_to_ansi(out) << std::endl; //输出消息到控制台显示
    }
}

void Client::disconnect() {
    ws.close(websocket::close_code::normal);// 关闭WebSocket连接
}

服务端——server.h

#ifndef WEBSOCKET_SERVER_H
#define WEBSOCKET_SERVER_H
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <thread>
#include <codecvt>
#include <wchar.h>
#include <locale.h>
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 = boost::asio::ip::tcp;       // from <boost/asio/ip/tcp.hpp>

class Server {
    public:
        static std::wstring string_to_wstring(const std::string& str);
        static std::string wstring_to_string(const std::wstring& ws);
        static std::string ansi_to_utf8(const std::string& s);
        static std::string utf8_to_ansi(const std::string& s);
        static void do_session(tcp::socket& socket, tcp::socket& socket1);
        static void initlization(std::string IP);
        static void initlization1(std::string IP);
};
#endif

服务端——server.cpp

#include "server.h"

std::wstring Server::string_to_wstring(const std::string& str) {
    std::wstring r;
    const char *source = str.c_str();
    wchar_t *dest = NULL;
    int len = 0;
    int ret = 0;
    len = strlen(source) + 1;
    if(len <= 1)
        return 0;
    dest = new wchar_t[len];
    ret = mbstowcs(dest, source, len);
    r = std::wstring(dest);
    delete[] dest;
	return r;
}

std::string Server::wstring_to_string(const std::wstring& ws) {
    std::string r = "";
    const wchar_t *source = ws.c_str();
    char *dest = NULL;
    int len = 0;
    int ret = 0;
    len = wcslen(source) + 1;
    if(len <= 1)
        return 0;
    dest = new char[len*sizeof(wchar_t)];
    ret = wcstombs(dest, source, len*sizeof(wchar_t));
    r = std::string(dest);
    delete[] dest;
	return r;
}

std::string Server::ansi_to_utf8(const std::string& s) {
    static std::wstring_convert<std::codecvt_utf8<wchar_t> > conv;
	return conv.to_bytes(string_to_wstring(s));
}

std::string Server::utf8_to_ansi(const std::string& s) {
    static std::wstring_convert<std::codecvt_utf8<wchar_t> > conv;
	return wstring_to_string(conv.from_bytes(s));
}

// socket 20000  socket1 19999
void Server::do_session(tcp::socket& socket, tcp::socket& socket1) {
    try
	{
		websocket::stream<tcp::socket> ws{ std::move(socket) };
		ws.set_option(websocket::stream_base::decorator(
			[](websocket::response_type& res)
		{
			res.set(http::field::server,
				std::string(BOOST_BEAST_VERSION_STRING) +
				" websocket-server-sync");
		}));
		websocket::stream<tcp::socket> ws1{ std::move(socket1) };
		ws1.set_option(websocket::stream_base::decorator(
			[](websocket::response_type& res)
		{
			res.set(http::field::server,
				std::string(BOOST_BEAST_VERSION_STRING) +
				" websocket-server-sync");
		}));
		ws.accept();//等待客户端连接
		ws1.accept();
		for (;;)
		{
			beast::flat_buffer buffer;// 这个缓冲区将保存传入的消息
			ws.read(buffer);// 读取一条消息
			auto out = beast::buffers_to_string(buffer.cdata());
			if (out != "") {
				ws1.write(net::buffer(ansi_to_utf8(out)));// 发送消息
			}
			sleep(1); //等待1秒
		}
	}
	catch (beast::system_error const& se)
	{
		if (se.code() != websocket::error::closed)
			std::cerr << "Error: " << se.code().message() << std::endl;
	}
	catch (std::exception const& e)
	{
		std::cerr << "Error: " << e.what() << std::endl;
	}
}
// socket 19999  socket1 20000
// void Server::do_session1(tcp::socket& socket, tcp::socket& socket1) {
//     try
// 	{
// 		websocket::stream<tcp::socket> ws{ std::move(socket) };
// 		ws.set_option(websocket::stream_base::decorator(
// 			[](websocket::response_type& res)
// 		{
// 			res.set(http::field::server,
// 				std::string(BOOST_BEAST_VERSION_STRING) +
// 				" websocket-server-sync");
// 		}));
// 		websocket::stream<tcp::socket> ws1{ std::move(socket1) };
// 		ws1.set_option(websocket::stream_base::decorator(
// 			[](websocket::response_type& res)
// 		{
// 			res.set(http::field::server,
// 				std::string(BOOST_BEAST_VERSION_STRING) +
// 				" websocket-server-sync");
// 		}));
// 		ws.accept();//等待客户端连接
// 		ws1.accept();
// 		for (;;)
// 		{
// 			beast::flat_buffer buffer;// 这个缓冲区将保存传入的消息
// 			ws.read(buffer);// 读取一条消息
// 			auto out = beast::buffers_to_string(buffer.cdata());
// 			if (out != "") {
// 				ws1.write(net::buffer(ansi_to_utf8(out)));// 发送消息
// 			}
// 			sleep(1); //等待1秒
// 		}
// 	}
// 	catch (beast::system_error const& se)
// 	{
// 		if (se.code() != websocket::error::closed)
// 			std::cerr << "Error: " << se.code().message() << std::endl;
// 	}
// 	catch (std::exception const& e)
// 	{
// 		std::cerr << "Error: " << e.what() << std::endl;
// 	}
// }

void Server::initlization(std::string IP) {
	try
	{
		auto const address = net::ip::make_address(IP);//绑定ip地址
		auto const port = static_cast<unsigned short>(std::atoi("20000"));//绑定端口号
		net::io_context ioc{ 1 };
		tcp::acceptor acceptor{ ioc,{ address, port } };
		auto const address1 = net::ip::make_address(IP);//绑定ip地址
		auto const port1 = static_cast<unsigned short>(std::atoi("19999"));//绑定端口号
		tcp::acceptor acceptor1{ ioc,{ address1, port1 } };
		for (;;)
		{
			tcp::socket socket{ ioc };
			acceptor.accept(socket);
			tcp::socket socket1{ ioc };
			acceptor1.accept(socket1);
			// 开启线程等待客户端的连接请求
			std::thread{ std::bind(&do_session,std::move(socket), std::move(socket1)) }.detach();
		}
	}
	catch (const std::exception & e) {
		std::cerr << "Error: " << e.what() << std::endl;
		return ;
	}
}

void Server::initlization1(std::string IP) {
	try
	{
		auto const address = net::ip::make_address(IP);//绑定ip地址
		auto const port = static_cast<unsigned short>(std::atoi("8888"));//绑定端口号
		net::io_context ioc{ 1 };
		tcp::acceptor acceptor{ ioc,{ address, port } };
		auto const address1 = net::ip::make_address(IP);//绑定ip地址
		auto const port1 = static_cast<unsigned short>(std::atoi("7777"));//绑定端口号
		tcp::acceptor acceptor1{ ioc,{ address1, port1 } };
		for (;;)
		{
			tcp::socket socket{ ioc };
			acceptor.accept(socket);
			tcp::socket socket1{ ioc };
			acceptor1.accept(socket1);
			// 开启线程等待客户端的连接请求
			std::thread{ std::bind(&do_session,std::move(socket), std::move(socket1)) }.detach();
		}
	}
	catch (const std::exception & e) {
		std::cerr << "Error: " << e.what() << std::endl;
		return ;
	}
}

客户端调用——客户1

#include "client.h"

Client client1_listen;
Client client1_send;
std::string listen_message = "";
std::string IP_server("192.168.1.116");
std::string send_message("client1 to client2");
const char *port_client1_send = "20000";
const char *port_client1_listen = "7777";

void listenThread() {
    client1_listen.connect(IP_server, port_client1_listen);  
    client1_listen.listen(listen_message);
}

void sendThread() {
    client1_send.connect(IP_server, port_client1_send);
    client1_send.send(send_message);
}

void outputThread() {
    while (1) {
        if (listen_message != "") {
            std::cout << listen_message << std::endl;
        }
        sleep(1);
    }
}

int main() { 
    std::thread sendThreadObj(sendThread);
    std::thread listenThreadObj(listenThread);
    std::thread outputThreadObj(outputThread);
    listenThreadObj.join();
    sendThreadObj.join();
    outputThreadObj.join();
    return 0;
}

客户端调用——客户2

#include "client.h"

Client client2_listen;
Client client2_send;
std::string listen_message = "";
std::string send_message("client2 to client1");
std::string IP_server("192.168.1.116");
const char *port_client2_send = "8888";
const char *port_client2_listen = "19999";

void listenThread() {
    client2_listen.connect(IP_server, port_client2_listen); 
    client2_listen.listen(listen_message);
}

void sendThread() {
    client2_send.connect(IP_server, port_client2_send);
    client2_send.send(send_message);
}

void outputThread() {
    while (1) {
        if (listen_message != "") {
            std::cout << listen_message << std::endl;
        }
        sleep(1);
    }
}

int main() { 
    std::thread sendThreadObj(sendThread);
    std::thread listenThreadObj(listenThread);
    std::thread outputThreadObj(outputThread);
    listenThreadObj.join();
    sendThreadObj.join();
    outputThreadObj.join();
    return 0;
}

服务端调用——服务1

#include "server.h"
#include <iostream>
#include <thread>

// 20000      19999
int main() {
    Server server;
    std::string IP("192.168.1.116");
    server.initlization(IP);
    return 0;
}

服务端调用——服务2

#include "server.h"
#include <iostream>
#include <thread>

// 18888 17777
int main() {
    Server server;
    std::string IP("192.168.1.116");
    server.initlization1(IP);
    return 0;
}

操作命令

g++ main_client1.cpp client.cpp client.h -o client1 -std=c++11 -lpthread
g++ main_client2.cpp client.cpp client.h -o client2 -std=c++11 -lpthread

g++ main_server.cpp server.cpp server.h -o server -std=c++11 -lpthread
g++ main_server1.cpp server.cpp server.h -o server1 -std=c++11 -lpthread

必须先server再client
./server
./server1
./client1
./client2

server:端口20000发  端口19999收
server1:端口8888发  端口7777

到了这里,关于C++实现websocket两server两client半双工通信(基于boost!!!)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Redis的实现一:c、c++的网络通信编程技术,先实现server和client的通信

    由于,本人是主修java的,所以以下内容可能不是很精通,各位看完后尽可评论。 以下皆是在linux的描述 Socket()函数 :创建用于通信的端点并返回描述符。 它的第一个参数 便是通信域,这里我举出常用的。 AF_INET是ipv4的。 AF_INET6是ipv6的。 它的第二个参数 便是套接字具有指定

    2024年01月16日
    浏览(41)
  • 全双工通信协议:WebSockets+STOMP

    WebSocket 协议定义了两种类型的消息(文本和二进制),但是它们的内容是未定义的。 STOMP (Streaming Text Oriented Messaging Protocol)是一种简单的、基于文本的消息传递协议,提供了一组命令和消息格式,用于在客户端和服务端之间发送和接收消息。客户端可以通过连接到消息代理(

    2024年02月20日
    浏览(44)
  • websocket实现go(server)与c#(client)通讯

    使用到github.com/gorilla/websocket C#操作websocket当客户端使用时使用 System.Net.Websockets 这个命名空间下的 ClientWebSocket 类 winform的设计界面如下: 代码如下: 注意:无论是客户端断开还是服务端断开,如果正在读取消息,则会触发错误。利用此机制可以很方便的处理重连问题。

    2024年02月06日
    浏览(32)
  • 使用 PHP WorkerMan 构建 WebSocket 全双工群聊通信(二)

    在很早很早以前,WebSocket 协议还没有被发明的时候,人们在 Web 端制作类实时数据动态更新时,一般采用轮询、 长连接 (Long Polling) 来实现。大概就是: 轮询:客户端不停发送 HTTP 请求给服务端,服务端返回最新数据 长连接:客户端发送一条 HTTP 请求给服务端,服务端 HOLD

    2024年02月09日
    浏览(37)
  • Linux网络编程:socket实现client/server通信

    阅读 UNIX网络编程 卷1:套接字联网API 第3版 的前4个章节,觉得有必要对书籍上的源码案例进行复现,并推敲TCP的C/S通信过程。 📌 测试环境:CentOS7.6 x64 编译server.c 和 client.c gcc server.c -g -std=gnu99 -o server 和 gcc client.c -g -std=gnu99 -o client 运行测试: 📌 server.c仅仅实现对单个客户

    2024年02月03日
    浏览(41)
  • UNIX网络编程:socket实现client/server通信

    阅读 UNIX网络编程 卷1:套接字联网API 第3版 的前4个章节,觉得有必要对书籍上的源码案例进行复现,并推敲TCP的C/S通信过程。 📌 测试环境:CentOS7.6 x64 编译server.c 和 client.c gcc server.c -g -std=gnu99 -o server 和 gcc client.c -g -std=gnu99 -o client 运行测试: 📌 server.c仅仅实现对单个客户

    2024年02月06日
    浏览(49)
  • Linux网络编程:socket & fork实现clients/server通信

    UNIX网络编程:socket实现client/server通信 随笔简单介绍了TCP Server服务单客户端的socket通信,但是并未涉及多客户端通信。 对于网络编程肯定涉及到多客户端通信和并发编程 (指在同时有大量的客户链接到同一服务器),故本随笔补充这部分知识。 而且并发并发编程涉及到多进程

    2024年02月05日
    浏览(51)
  • C++毕业设计——基于 C+++TCP+Websocket的即时通信系统设计与实现(毕业论文+程序源码)——即时通信系统

    大家好,今天给大家介绍基于 C+++TCP+Websocket的即时通信系统设计与实现,文章末尾附有本毕业设计的论文和源码下载地址哦。需要下载开题报告PPT模板及论文答辩PPT模板等的小伙伴,可以进入我的博客主页查看左侧最下面栏目中的自助下载方法哦 文章目录: 随着网络通信和

    2024年02月08日
    浏览(41)
  • UNIX网络编程:socket & fork()多进程 实现clients/server通信

    UNIX网络编程:socket实现client/server通信 随笔简单介绍了TCP Server服务单客户端的socket通信,但是并未涉及多客户端通信。 对于网络编程肯定涉及到多客户端通信和并发编程 (指在同时有大量的客户链接到同一服务器),故本随笔补充这部分知识。 而且并发并发编程涉及到多进程

    2024年02月06日
    浏览(51)
  • Linux网络编程:socket & fork()多进程 实现clients/server通信

    UNIX网络编程:socket实现client/server通信 随笔简单介绍了TCP Server服务单客户端的socket通信,但是并未涉及多客户端通信。 对于网络编程肯定涉及到多客户端通信和并发编程 (指在同时有大量的客户链接到同一服务器),故本随笔补充这部分知识。 而且并发并发编程涉及到多进程

    2024年02月05日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包