webrtc建联流程图
由上图可知,所谓的信令服务器其实就是将peer的offer/candidate/answer传给对端而已。这样的话实现方式就有很多种了,目前普遍的方式HTTP/HTTPS,WS/WSS。像webrtc-demo-peerconnection就是实现HTTP这种方式。本文使用WS(websocket)来实现。
简单的协议
peer签到
发送
|-----------|--------|
| src | type |
| 就是peer的名称 | signin |
返回
|------------|------|-----|
| type | code | msg |
| signin_ack | 返回码 | 消息 |
peer数据传输
发送
|-------|-------|-------|------|
| src | dst | type | 其他内容 |
| 发送端名称 | 接收端名称 | trans | ... |
返回
|-----------|------|-----|
| type | code | msg |
| trans_ack | 返回码 | 消息 |
实现代码
1、下载websocketpp/jsoncpp代码:github上找
2、下载boost库
3、先使用cmake生成VS工程,然后编译jsoncpp
4、创建工程SignalServer
主代码如下:
#include "pch.h"
#include <iostream>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
#include <json/json.h>
typedef websocketpp::server<websocketpp::config::asio> server;
server signalserver;
std::mutex g_wcmutex;
std::map<std::string, websocketpp::connection_hdl> g_mapWcInfo;
void on_message(websocketpp::connection_hdl hdl, server::message_ptr msg)
{
std::string strMsg = msg->get_payload();
//解析json
Json::Reader reader;
Json::Value jMsg;
if (!reader.parse(strMsg, jMsg))
{
return;
}
//获取当前的用户名称
std::string strSrcName;
Json::Value jName;
if (!jMsg.isMember("src"))
{
return;
}
jName = jMsg["src"];
strSrcName = jName.asString();
//获取当前的操作
std::string strOptType;
Json::Value jOptType;
if (!jMsg.isMember("type"))
{
return;
}
jOptType = jMsg["type"];
strOptType = jOptType.asString();
//数据转发
if (strOptType.compare("signin") == 0)//peer签到
{
try {
g_wcmutex.lock();
g_mapWcInfo[strSrcName] = hdl;
g_wcmutex.unlock();
signalserver.send(hdl, "{\"type_ack\":\"signin\",\"code\":200,\"msg\":\"success\"}", websocketpp::frame::opcode::text);
}
catch (websocketpp::exception const & e) {
std::cout << "Echo failed because: "
<< "(" << e.what() << ")" << std::endl;
}
}
else if (strOptType.compare("trans") == 0)//数据转发
{
std::string strDstName;
Json::Value jDstName;
if (!jMsg.isMember("dst"))
{
return;
}
jDstName = jMsg["dst"];
strDstName = jDstName.asString();
g_wcmutex.lock();
if (g_mapWcInfo.find(strDstName) == g_mapWcInfo.end())
{
g_wcmutex.unlock();
signalserver.send(hdl, "{\"trans_ack\":\"trans\",\"code\":201,\"msg\":\"failed\"}", websocketpp::frame::opcode::text);
return;
}
else
{
signalserver.send(g_mapWcInfo[strDstName], strMsg, websocketpp::frame::opcode::text);
signalserver.send(hdl, "{\"trans_ack\":\"trans\",\"code\":200,\"msg\":\"success\"}", websocketpp::frame::opcode::text);
}
g_wcmutex.unlock();
}
}
void on_close(websocketpp::connection_hdl hdl)
{
server::connection_ptr ptr = signalserver.get_con_from_hdl(hdl);
g_wcmutex.lock();
std::map<std::string, websocketpp::connection_hdl>::iterator it = g_mapWcInfo.begin();
while (it != g_mapWcInfo.end())
{
server::connection_ptr ptr1 = signalserver.get_con_from_hdl(it->second);
if (ptr1 == ptr)
{
g_mapWcInfo.erase(it);
break;
}
}
g_wcmutex.unlock();
}
int main()
{
signalserver.set_close_handler(&on_close);
signalserver.set_message_handler(&on_message);
signalserver.set_access_channels(websocketpp::log::alevel::all);
signalserver.set_error_channels(websocketpp::log::elevel::all);
signalserver.init_asio();
signalserver.listen(9002);
signalserver.start_accept();
signalserver.run();
}
使用网页在线websocket测试:websocket在线测试
上面是一个最简的信令服务器。