socket.io 官网的C++版的客户端。https://github.com/socketio/socket.io-client-cpp
并不依赖boost了,所以相对比较好安装,但是还是有不少明坑,暗坑。还是得写下来
自带的example太复杂了,一个简单的控制台程序塞进大量没P用的东西,什么mutex都来了。https://github.com/socketio/socket.io-client-cpp/blob/master/examples/Console/main.cpp
自己写1个精简版的控制台,特定windows平台下VS2019。
一、编译
1.1 openssl
1.1.1 直接下载windows x64的编译好的版本:http://slproweb.com/products/Win32OpenSSL.html
1.1.2 安装到 D:\lib\OpenSSL-Win64
1.1.3 建立2个环境变量,以后似乎是openssl自用,1个是下面cmake编译socket.io-client-cpp需要的。这里全都设置好
OPENSSL_HOME
D:\lib\OpenSSL-Win64\bin
OPENSSL_ROOT_DIR
D:\lib\OpenSSL-Win64
1.2 下载编译
基本就是按官网 https://github.com/socketio/socket.io-client-cpp/blob/master/INSTALL.md#with-cmake
1.2.1 下载
git clone --recurse-submodules https://github.com/socketio/socket.io-client-cpp.git
一旦遇到任何433 Time out
请直接设置代理。
注意直接全局设置代理:
git config --global http.proxy 127.0.0.1:1080
而不要只在这一个语句设置代理。
$ git clone --recurse-submodules https://github.com/socketio/socket.io-client-cpp.git --config "http.proxy=127.0.0.1:1080"
否则只是下载socket.io-client-cpp时用到了代理,而下载依赖工程的时候,还是不用代理。
或者10053 啥的错误,
git config --global http.sslVerify "false"
1.2.2 编译
安装cmake。
cd 到 clone下来的源码 路径 :比如 D:\lib\socket.io-client-cpp
用gui版打开,
设置
CMAKE_INSTALL_PREFIX = D:/lib/sioclient
防止默认安装到C:/Program Files (x86)/sioclient 会在后面打开sln时麻烦
注意不要直接打开。而是要在开始菜单,找到vs2019的图标,右键,"更多"-> "以管理员身份运行" (否则会在INSTALL时报错 setlocal,没有管理员权限就不能在C盘创建文件夹)
configure generate
会在这里产生vs2019版本的 sln
然后再选这个sln,
注意,编译出的lib比较坑爹,并没有区分release和debug 也就是debug没有叫 sioclient_d.lib
选择,先Debug后release x64
然后就简单了,在项目管理器里先生成 ALL_BUILD 再 INSTALL。
install到 D:/lib/sioclient
里面include里3个.h文件:
sio_client.h
sio_message.h
sio_socket.h
lib里4个静态库lib
sioclient.lib
sioclient_tls.lib
debug install后手工把这2个改名为
sioclient_d.lib
sioclient_tls_d.lib
把sioclient文件夹整体复制到d:/lib里,作为自己demo使用的依赖项。
至此编译完毕。
二、测试
用py写一个测试用的server
from gevent import monkey
monkey.patch_all()
from flask_socketio import SocketIO
from flask_socketio import send, emit
from flask_cors import CORS
from flask import Flask, render_template, session, request, jsonify
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
app.config['JSON_AS_ASCII'] = False
CORS(app)
#socketio = SocketIO(app, async_mode="gevent", ping_timeout=10, cors_allowed_origins='*', cors_credentials=False)
socketio = SocketIO(app, ping_timeout=10, cors_allowed_origins='*', cors_credentials=False)
@app.route('/', methods=['GET'])
def handle_target_kind():
return 'hello world'
emit('m1')
#-------------socketio---------------------
@socketio.on('connect')
def handle_connect():
print('connect')
emit('from server', '哈哈哈')
@socketio.on('disconnect')
def handle_disconnect():
print('Client disconnected', request.sid)
@socketio.on('message_empty')
def handle_message_empty():
print('message_empty')
@socketio.on('message_str')
def handle_message_str(data):
print('message_str ', data)
@socketio.on('message_two')
def message_two(d1, d2):
print('message_two ', d1, d2)
# @sio.event
# def message_list(sid, data):
# print('message_list ', data)
# @sio.event
# def message_list(sid, data):
# print('message_list ', data)
if __name__ == '__main__':
print('flask socketio start')
socketio.run(app, host='0.0.0.0', port=5000)
cpp客户端
#include <iostream>
#include <sio_client.h>
#include <sio_message.h>
#include <sio_socket.h>
using namespace sio;
using namespace std;
void OnConnect(sio::event &)
{
//不能在OnConnect里emit!
std::cout << "connected \n";
}
void OnTargetChanged(sio::event& ev)
{
std::cout << "OnTargetChanged \n";
//接收消息
const sio::message::list message_received = ev.get_message();
std::cout << message_received.size() << std::endl;
//必须转成特定类型的消息
std::cout << message_received[0]->get_string() << std::endl;
//其他消息里可以emit
message::list li("sports");
li.push(string_message::create("economics"));
current_socket->emit("message_two", li);
}
int main()
{
socket::ptr current_socket;
sio::client h;
h.connect("http://127.0.0.1:5000");
current_socket = h.socket();
current_socket->on("connect", &OnConnect);
current_socket->on("target_changed", &OnTargetChanged);
//如果需要在连接时发送消息,需要在connect外面emit
message::list para("worker");
current_socket->emit("online", para);
//current_socket->on("connect", &OnMessage);
while (true) {
}
std::cout << "Hello World!\n";
h.sync_close();
h.clear_con_listeners();
return 0;
}
这是最简单版本的demo了,连接上不用等待,就可以直接emit,但是必须后面跟1个while 死等,这样就能收发到。
注意不能在onconnect里emit。GitHub上也有人问这个
如果想连接成功后立即发送什么,直接写在外面。
接收消息时 先转型为message::list, 再具体转型。
—————————————