前言
Socket.IO C++基于Boost和WebSocket++,可在多平台上工作(跨平台)。此通信类似于websocket,但是不通用于websocket。
Sockect.io 与Websocket的区别
我在知乎上看到说明两者的区别,感觉比较详细
WebSocket和Socket.io之间的区别(译) - 知乎 (zhihu.com)
Sockect.IO编译
Socket.IO-Client-cpp编译——C++_十年之少的博客-CSDN博客
代码说明
我是比照着 官方的给的示例(socket.io-client-cpp-master/examples/QT/SioChatDemo)进行学习的,官方的示例说明网址是Socket.IO C++ | Socket.IO。
- 在.h文件上设置命名空间:
using namespace sio;
- 获取套接字(socket),可获取含有命名的套件字,具体看需求;
socket::ptr sock = _io->socket();
// socket::ptr sock = _io->socket("nsp");
- 监听套接字的事件,如新消息、用户加入、用户离开等;需要用到socket::on函数,他有两种形式,如下
typedef std::function<void(const std::string& name,message::ptr const& message,
bool need_ack, message::list& ack_message)> event_listener_aux;
typedef std::function<void(event& event)> event_listener;
void on(std::string const& event_name,event_listener const& func);
void on(std::string const& event_name,event_listener_aux const& func);
很明显,示例里用的是第二种形式,回调函数的格式必须是:
void funcName (const std::string& name,message::ptr const& message,bool need_ack,
message::list& ack_message)
name :消息名
message:消息数据句柄
need_ack:是否需要确认
ack_message:确认的消息
#ifdef WIN32
#define BIND_EVENT(IO,EV,FN) \
do{ \
socket::event_listener_aux l = FN;\
IO->on(EV,l);\
} while(0)
#else
#define BIND_EVENT(IO,EV,FN) \
IO->on(EV,FN)
#endif
void MainWindow::MainWindow(...)
{
...
using std::placeholders::_1;
using std::placeholders::_2;
using std::placeholders::_3;
using std::placeholders::_4;
BIND_EVENT(sock,"new message",std::bind(&MainWindow::OnNewMessage,
this,_1,_2,_3,_4));
...
}
void MainWindow::OnNewMessage(std::string const& name,message::ptr const& data,
bool hasAck,message::list &ack_resp)
{
if(data->get_flag() == message::flag_object)
{
std::string msg = data->get_map()["message"]->get_string();
std::string username = data->get_map()["username"]->get_string();
QString label = QString::fromUtf8(username.data(),username.length());
label.append(" : ");
label.append(QString::fromUtf8(msg.data(),msg.length()));
QListWidgetItem *item= new QListWidgetItem(label);
Q_EMIT RequestAddListItem(item);
}
}
- 监听客户端的某些事件,如客户端的关闭连接等;
_io->set_close_listener(std::bind(&MainWindow::OnClosed,this,_1));
void MainWindow::OnClosed(client::close_reason const& reason)
{
Q_EMIT RequestToggleInputs(false);
}
- 创建连接
#define kURL "http://localhost:3000"
_io->connect(kURL);
- 发送消息:用socket的方法emit进行发送
void emit(std::string const& name, message::list const& msglist = nullptr, std::function<void (message::list const&)> const& ack = nullptr);
void MainWindow::OnConnected(std::string const& nsp)
{
QByteArray bytes = m_name.toUtf8();
std::string nickName(bytes.data(),bytes.length());
_io->socket()->emit("add user", nickName);
}
运行程序
要想玩转示例程序,还需要注意各方努力:
- 客户端:
1>检查pro文件:在运行前 需要检查SioChatDemo.pro文件所配置的动态库位置;
2>确认填写的服务器的地址;
- 服务器:
1>下载服务器代码:https://github.com/Automattic/socket.io/tree/master/examples/chat
2>按照命令运行服务器:
$ npm i
$ npm start
当命令行出现:Server listening at port 3000,表示运行成功。
效果图
结束语
此次学习Socket.IO真是有点费劲,虽然代码看着挺清楚,但是环境这块真的费大劲了:编译客户端库、编译Boost、下载服务器代码及运行,其中的弯路不必说。