websocket 是一个基于tcp的应用层协议,在网页端开发经常会用到。一开始我以为websocket库也像C#、java、javascript 那样,几句话搞定。
using (var ws = new WebSocket ("ws://dragonsnest.far/Laputa")) {
ws.OnMessage += (sender, e) =>
Console.WriteLine ("Laputa says: " + e.Data);
ws.Connect ();
ws.Send ("BALUS");
Console.ReadKey (true);
}
随便挑个看得顺眼的库就行,然后就陷入无穷无尽的踩坑之旅。
libwebsockets 库,编译起来很容易,但是一个client示例demo 洋洋洒洒1000 多行,顿时心生退意。虽然实际使用没那么麻烦,但是不出问题还好,一出问题,那个回调参数的状态转换能把人绕晕。而且用来传输视频流,数据量大的时候总有莫名其妙的断流问题。算了,性能再高我也用不着,只是简单的作为客户端使用,懒得折腾。
websocketpp ,这个比 libwebsockets友好得多,示例啥得都比较简单。但是它依赖boost库,我直接下载windows 编译好的boost库 都有1个G磁盘空间,编译能正常跑起来,也没有啥断流问题。但不知道为啥同样的代码编译进dll后,C# 一调用就崩溃了,拦都不拦不住,我也没去追踪了,比较搞定这个还有boost 依赖,部署很麻烦。
知乎有人推荐nopoll 库,我也试用过,调用接口简单明了,有官网和官方文档,支持Linux、window等,依赖库就只有openssl。不过这个库也有一些坑,windows下有时候会报连接错误,而且要自己处理分片,超长数据需要自己拼接等。
kuma,这个是最近使用的,客户端代码很简单,没什么依赖,windows 下VS编译很舒服,一路通畅。
#include "kmapi.h"
#include "libkev/src/util/defer.h"
using namespace kuma;
int main(int argc, char *argv[])
{
kuma::init();
DEFER(kuma::fini());
EventLoop main_loop(PollType::NONE);
if (!main_loop.init()) {
printf("failed to init EventLoop\n");
return -1;
}
WebSocket ws(&main_loop, "HTTP/1.1");
ws.setOpenCallback([] (KMError err) {
printf("ws.onOpen, err=%d\n", err);
});
ws.setDataCallback([] (KMBuffer &data, bool is_text, bool is_fin) {
printf("ws.onData, len=%lu\n", data.chainLength());
});
ws.setWriteCallback([] (KMError err) {
printf("ws.onWrite, write available\n");
});
ws.setErrorCallback([] (KMError err) {
printf("ws.onError, err=%d\n", err);
});
ws.setSubprotocol("jws");
ws.setOrigin("www.jamol.cn");
ws.connect("wss://127.0.0.1:8443/");
Timer timer(&main_loop);
timer.schedule(1000, Timer::Mode::ONE_SHOT, [] {
printf("onTimer\n");
});
main_loop.loop();
return 0;
}
Bug 还是有的,提过几次bug,作者回复很及时,bug 修复得也快,暂时凑合着用。