热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Windows下使用websocketpp

WebSocketprotocol是HTML5一种新的协议,它是实现了浏览器与服务器全双工通信。WebSocket协议解析参考这篇文章http:www.cnblogs

WebSocket protocol 是HTML5一种新的协议,它是实现了浏览器与服务器全双工通信。WebSocket协议解析参考这篇文章http://www.cnblogs.com/chyingp/p/websocket-deep-in.html

一、下载websocketpp、boost、openssl
WebSocketpp只是一个库,本身不需要搭建什么环境,只要新建的项目引入相关的库就行。但是WebSocketpp依赖于boost库和openssl库,这两个库需要编译生成lib库文件,在使用WebSocketpp库的工程中,需要引入boost库和openssl库的头文件和lib文件。openssl库是可选的。
https://github.com/zaphoyd/websocketpp
https://sourceforge.net/projects/boost/files/boost/1.62.0/ 下载boost最新版本1.62.0
https://github.com/openssl/openssl/releases下载openssl1.1.0版本

websocket使用wss协议,使用websocketpp库时,需要使用openssl库支持。
在工程属性中添加openssl头文件目录引用,增加openssl库文件目录引用。
在工程代码中添加对openssl部份引用:
#pragma comment(lib, "libeay32.lib")
#pragma comment(lib, "ssleay32.lib")

二、新建一个vs工程,书写websocket相关代码,配置工程属性。
第一步,把boost的根目录添加到include。
第二步,把websoketpp的子目录添加到include,比如将websocketpp-0.8.1中websoketpp目录拷贝本工程中,同时添加到include
第三步,把boost/stage/lib添加到静态库。
websocketpp-0.8.1中examples目录中有很少实例代码,可以参考。


1、出现错误    C4996    'std::copy::_Unchecked_iterators::_Deprecate': Call to 'std::copy' with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'    WebSocketTest    c:\program files (x86)\microsoft visual studio 14.0\vc\include\xutility    2372    
解决方法:添加参数“_SCL_SECURE_NO_WARNINGS”(SCL安全无警告,S代表Safety 安全、C代表Check检查、L代表List清单)到预处理器定义中,不警告这种不安全的操作方式,方法如下:
项目->属性->配置属性->C/C++->预处理器->预处理器定义(末尾加上“_SCL_SECURE_NO_WARNINGS”即可(注意分号隔开))
2、在ie9-ie11浏览器测试成功。在edge浏览器中测试,发现不成功。在chrome浏览器中测试成功。
3、tcp连接建立之后接受数据,解析http请求websocket upgrade命令,成功失败做对应的处理,参考connection_impl.hpp文件
connection_impl.hpp文件的handle_read_http_response函数解析客户端数据。
3.1)http请求是websocket upgrade命令,执行log_open_result
        3.1.1)执行open handler回调函数,在此函数函数中可以获取到客户端的请求方法、命令、参数等。
        3.1.2)handle_read_frame读取帧数据
3.2)http请求非websocket upgrade命令,返回错误,terminate关闭连接。

三、服务器实例代码

// WebSocketTest.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"#include
#include
#include
#include #include
#include
#include //名称与值数据对
struct NameAndValue
{std::string strName;std::string strValue;
};
// 字符串分割
int StringSplit(std::vector& dst, const std::string& src, const std::string& separator);
//去前后空格
std::string& StringTrim(std::string &str);
//获取请求命令与参数
bool GetReqeustCommandAndParmeter(std::string strUri, std::string & strRequestOperateCommand, std::list & listRequestOperateParameter);typedef websocketpp::server server;using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;// pull out the type of messages sent by our config
typedef server::message_ptr message_ptr;bool validate(server *, websocketpp::connection_hdl) {//sleep(6);return true;
}void on_http(server* s, websocketpp::connection_hdl hdl) {server::connection_ptr con &#61; s->get_con_from_hdl(hdl);std::string res &#61; con->get_request_body();std::stringstream ss;ss <<"got HTTP request with " <set_body(ss.str());con->set_status(websocketpp::http::status_code::ok);
}void on_fail(server* s, websocketpp::connection_hdl hdl) {server::connection_ptr con &#61; s->get_con_from_hdl(hdl);std::cout <<"Fail handler: " <get_ec() <<" " <get_ec().message() <}void on_open(server* s, websocketpp::connection_hdl hdl) {//申请websocket upgrade成功之后&#xff0c;调用open_handler函数&#xff0c;回调on_open。//在这里&#xff0c;可以获取http请求的地址、参数信息。std::cout <<"open handler" <get_con_from_hdl(hdl);websocketpp::config::core::request_type requestClient &#61; con->get_request();std::string strMethod &#61; requestClient.get_method(); //请求方法std::string strUri &#61; requestClient.get_uri(); //请求uri地址&#xff0c;可以解析参数std::string strRequestOperateCommand &#61; ""; //操作类型std::list listRequestOperateParameter; //操作参数列表 GetReqeustCommandAndParmeter(strUri, strRequestOperateCommand, listRequestOperateParameter);std::cout <<"command:" <}void on_close(websocketpp::connection_hdl hdl) {std::cout <<"Close handler" <}// Define a callback to handle incoming messages
void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {/*hdl.lock().get() 获得连接标识msg->get_payload() 是收到的消息内容msg->get_opcode() 是收到消息的类型 &#xff0c;包含&#xff1a;文本TEXT,二进制BINARY等等*/std::cout <<"on_message called with hdl: " <get_payload()<send(hdl, //连接msg->get_payload(), //消息msg->get_opcode());//消息类型*/s->send(hdl, msg->get_payload(), msg->get_opcode());}catch (websocketpp::exception const & e) {std::cout <<"Echo failed because: "<<"(" <}int main() {server print_server;try {// Set logging settingsprint_server.set_access_channels(websocketpp::log::alevel::all);print_server.set_error_channels(websocketpp::log::elevel::all);//print_server.clear_access_channels(websocketpp::log::alevel::frame_payload);// Register our message handlerprint_server.set_message_handler(bind(&on_message, &print_server, ::_1, ::_2));print_server.set_http_handler(bind(&on_http, &print_server, ::_1));print_server.set_fail_handler(bind(&on_fail, &print_server, ::_1));print_server.set_open_handler(bind(&on_open, &print_server, ::_1));print_server.set_close_handler(bind(&on_close, ::_1));print_server.set_validate_handler(bind(&validate, &print_server, ::_1));// Initialize ASIOprint_server.init_asio();print_server.set_reuse_addr(true);// Listen on port 9100print_server.listen(9100);// Start the server accept loopprint_server.start_accept();// Start the ASIO io_service run loopprint_server.run();//stopprint_server.stop();}catch (websocketpp::exception const & e) {std::cout <}// 字符串分割
int StringSplit(std::vector& dst, const std::string& src, const std::string& separator)
{if (src.empty() || separator.empty())return 0;int nCount &#61; 0;std::string temp;size_t pos &#61; 0, offset &#61; 0;// 分割第1~n-1个while ((pos &#61; src.find_first_of(separator, offset)) !&#61; std::string::npos){temp &#61; src.substr(offset, pos - offset);if (temp.length() > 0) {dst.push_back(temp);nCount&#43;&#43;;}offset &#61; pos &#43; 1;}// 分割第n个temp &#61; src.substr(offset, src.length() - offset);if (temp.length() > 0) {dst.push_back(temp);nCount&#43;&#43;;}return nCount;
}
//去前后空格
std::string& StringTrim(std::string &str)
{if (str.empty()) {return str;}str.erase(0, str.find_first_not_of(" "));str.erase(str.find_last_not_of(" ") &#43; 1);return str;
}
//获取请求命令与参数
bool GetReqeustCommandAndParmeter(std::string strUri, std::string & strRequestOperateCommand, std::list & listRequestOperateParameter)
{bool bRet &#61; false;std::vector vecRequest;int nRetSplit &#61; StringSplit(vecRequest, strUri, "?");if (nRetSplit > 0){if (vecRequest.size() &#61;&#61; 1){strRequestOperateCommand &#61; vecRequest[0];}else if (vecRequest.size() > 1){strRequestOperateCommand &#61; vecRequest[0];std::string strRequestParameter &#61; vecRequest[1];std::vector vecParams;nRetSplit &#61; StringSplit(vecParams, strRequestParameter, "&");if (nRetSplit > 0){std::vector::iterator iter, iterEnd;iter &#61; vecParams.begin();iterEnd &#61; vecParams.end();for (iter; iter !&#61; iterEnd; iter&#43;&#43;){std::vector vecNameOrValue;nRetSplit &#61; StringSplit(vecNameOrValue, *iter, "&#61;");if (nRetSplit > 0){NameAndValue nvNameAndValue;nvNameAndValue.strName &#61; vecNameOrValue[0];nvNameAndValue.strValue &#61; "";if (vecNameOrValue.size() > 1){nvNameAndValue.strValue &#61; vecNameOrValue[1];}//insertlistRequestOperateParameter.push_back(nvNameAndValue);}}}}else{}}return bRet;
}

四、web客户端实例代码

test.html


代码下载

 

WebSocket在线测试工具&#xff1a;http://ws.douqq.com/


推荐阅读
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • 如何搭建Java开发环境并开发WinCE项目
    本文介绍了如何搭建Java开发环境并开发WinCE项目,包括搭建开发环境的步骤和获取SDK的几种方式。同时还解答了一些关于WinCE开发的常见问题。通过阅读本文,您将了解如何使用Java进行嵌入式开发,并能够顺利开发WinCE应用程序。 ... [详细]
  • svnWebUI:一款现代化的svn服务端管理软件
    svnWebUI是一款图形化管理服务端Subversion的配置工具,适用于非程序员使用。它解决了svn用户和权限配置繁琐且不便的问题,提供了现代化的web界面,让svn服务端管理变得轻松。演示地址:http://svn.nginxwebui.cn:6060。 ... [详细]
  • 本文介绍了如何在Azure应用服务实例上获取.NetCore 3.0+的支持。作者分享了自己在将代码升级为使用.NET Core 3.0时遇到的问题,并提供了解决方法。文章还介绍了在部署过程中使用Kudu构建的方法,并指出了可能出现的错误。此外,还介绍了开发者应用服务计划和免费产品应用服务计划在不同地区的运行情况。最后,文章指出了当前的.NET SDK不支持目标为.NET Core 3.0的问题,并提供了解决方案。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • HTML5网页模板怎么加百度统计?
    本文介绍了如何在HTML5网页模板中加入百度统计,并对模板文件、css样式表、js插件库等内容进行了说明。同时还解答了关于HTML5网页模板的使用方法、表单提交、域名和空间的问题,并介绍了如何使用Visual Studio 2010创建HTML5模板。此外,还提到了使用Jquery编写美好的HTML5前端框架模板的方法,以及制作企业HTML5网站模板和支持HTML5的CMS。 ... [详细]
  • 本文介绍了Python语言程序设计中文件和数据格式化的操作,包括使用np.savetext保存文本文件,对文本文件和二进制文件进行统一的操作步骤,以及使用Numpy模块进行数据可视化编程的指南。同时还提供了一些关于Python的测试题。 ... [详细]
  • 本文记录了作者对x265开源代码的实现与框架进行学习与探索的过程,包括x265的下载地址与参考资料,以及在Win7 32 bit PC、VS2010平台上的安装与配置步骤。 ... [详细]
author-avatar
小賑賑_533
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有