目录html
5. b/s通讯websocket
6. c/s通讯网络
7. 性能异步
WebSocket用于在Web浏览器和服务器之间进行数据传输的一种技术。固然若是非要用它搞定cs通讯,也是能够的。socket
Socket是传输控制层协议,WebSocket是应用层协议。async
Socket是应用层与TCP/IP协议族通讯的中间软件抽象层,它是一组接口。它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来讲,一组简单的接口就是所有,让Socket去组织数据,以符合指定的协议。
WebSocket 则不一样,它是一个完整的 应用层协议,包含一套标准的 API,能够把WebSocket想象成HTTP,HTTP和Socket什么关系,WebSocket和Socket就是什么关系。
都是应用层协议,都是基于TCP的。可是HTTP是单向数据流,客户端向服务端发送请求,服务端响应并返回数据;Websocket链接后能够实现客户端和服务端双向数据传递。
HTTP协议是非持久化的,单向的网络协议,在创建链接后只容许浏览器向服务器发出请求后,服务器才能返回相应的数据。当须要即时通信时,经过轮询在特定的时间间隔(如1s),由浏览器向服务器发送Request请求,而后将最新的数据返回给浏览器。这样的方法最明显的缺点就是须要不断的发送请求,并且一般HTTP request的Header是很是长的,为了传输一个很小的数据 须要付出巨大的代价,是很不合算的,占用了不少的宽带。每一次请求、应答,都浪费了必定流量在相同的头部信息上
然而WebSocket的出现能够弥补这一缺点。在WebSocket中,只须要服务器和浏览器经过HTTP协议进行一个握手的动做,而后单独创建一条TCP的通讯通道进行数据的传送。
Beast是boost的一个网络库,经过使用一致的Boost.Asio异步模型提供低级HTTP / 1,WebSocket网络协议和算法,可做为编写可互操做的网络库的基础。
该库设计用于:
该库不是客户端或服务器,可是能够用来构建那些东西。提供了许多示例,包括客户端和服务器,能够用做编写本身的程序的起点。
Beast容许用户使用HTTP / 1和WebSocket建立本身的库,客户端和服务器。由于Beast会处理底层协议细节,因此代码将更容易,更快地实现,理解和维护。HTTP和WebSocket协议驱动了大多数万维网。每一个Web浏览器都实现这些协议以加载网页并容许客户端程序(一般用JavaScript编写)进行交互通讯。C ++得益于这些协议的标准化实现。
browser端:咱们用http://www.websocket-test.com/来充当b端
Server端实现以下:
首先有个WebSocketServer类。用来接收browser发送的指令并反馈发送成功或者失败。代码以下:
typedef boost::function<void(boost::beast::multi_buffer& request, boost::beast::multi_buffer& response)> ResquestCallback; class WebSocketServer { public: WebSocketServer(boost::asio::io_context& io_ctx); ~ WebSocketServer() public: bool Listen(uint16 port); bool IsActive() const; void Shutdown(); void SetCallback(RequestCallback callback); private: boost::asio::io_context ctx_; RequestCallback callback_; }
其次有一个WebSocketPublishServer类,用来向订阅的客户端发布数据。
class WebSocketPublishServer { public: static WebSocketPublishServer* Instance(); public: void SetIoContext(std::shared_ptr<boost::asio::io_context> ctx); bool Listen(uint16 port); bool IsActive() const; void Shutdown(); void publish(const std::string& msg); private: WebSocketPublishServer (); ~ WebSocketPublishServer () private: std::share_ptr<publisher> publisher_; std:shared_ptr<asio::io_context> ioc_ uint16 port; } class subscriber : public std::enable_shared_from_this<subscriber> { public: explicit subscriber(tcp::socket sockt, std::weak_ptr<publisher> pub): ws_(std::move(socket)), publish(pub) { is_sending.store(false); } public: void run(); void write(beast::multi_buffer buffer); private: std::weak_ptr<publisher> pub_; websocket::stream<tcp::socket> ws_; std::atomic<bool> is_sending_; boost::mutex cache_buffer_mutex_; beast::multi_buffer read_buffer_; beast::multi_buffer write_buffer_; beast::multi_buffer cache_buffer_; }; class publisher : public std::enable_shared_from_this< publisher > { public: publisher(asio::io_context& ioc, tcp::endpoint endp); public: void run(); bool publish(const std::string& str); private: std::vector< subscriberPtr > subscribers_; tcp::acceptor acceptor_; tcp::socket socket_; }
c/s通讯server端同b/s部分的WebsocketServer和WebSocketPublishServer
咱们只须要补充一个异步发送客户端WebsocketAsyncClient类,代码以下:
typedef boost::function<void(WebSocketReply)> WebSocketCallback; class WebsocketAsyncClient { public: WebsocketAsyncClient(); ~ WebsocketAsyncClient(); public: bool AsyncConnect(const std::string& ip; short potr); bool AsyncSendCommand(const std::string& commad, WebSocketCallback callback); bool AsyncSubscribe(WebSocketCallback callback); bool AsyncUnSubscribe(); private: asio::io_context ioc_; asio::executor_work_guard<asio::io_context::executor_type>work_guard_; std::shared_ptr<command> command_; std::shared_ptr<subscriber> subscriber_; std::string address_; std:string port_; } typedef std:pair<std::string, WebSocketCallback> CommandPair; class command : public std::enable_shared_from_this<command> { public: explicit command(asio::io_context& ioc); bool connec(const std::string& ip, short port); bool asyncSendCommand(const std:string& command, WebSocketCallback callback); private: tcp::resolver resolver_; beast::websocket::stream<tcp::socket> ws_; beast::multi_buffer buffer_; boost::system::error_code ec_; std::string address_; std::string port_; std::queue< CommandPair > requests_; bool isRequesting_; } class subscriber : public std::enable_shared_from_this< subscriber > { public: explicit subscriber (asio::io_context& ioc); bool connec(const std::string& ip, short port); void setCallback(WebSocketCallback cb); void unsubscribe(); private: tcp::resolver resolver_; beast::websocket::stream<tcp::socket> ws_; beast::multi_buffer buffer_; boost::system::error_code ec_; std::string address_; atd::string port_; WebSocketCallback callback_; Volatile bool cancled_; }
用websocket实现c/s通讯的性能应该是个关注点,基于上面的实现,简单测试结果以下: