WebRTC Native框架(五)(1)

delete s;  // sorry, that’s all we can take.

printf(“Connection limit reached\n”);

} else {

//如果新连接被成功添加到SocketArray中,则中断会打印改信息

sockets.push_back(s);

printf(“New connection…\n”);

}

}

//在后续的循环中,由于SocketArray中有新的连接,所以会进入如下逻辑

for (SocketArray::iterator i = sockets.begin(); i != sockets.end(); ++i) {

DataSocket* s = *i;

if (FD_ISSET(s->socket(), &socket_set)) {

if (s->OnDataAvailable(&socket_done) && s->request_received()) {

//从服务端注册列表中,检索这个client,由于是for循环从begin到end的遍历,

//所以遍历完了之后,所有客户端界面都会显示连上服务器的其它客户端,这样想和谁通信,

//客户端上点击对应的客户端项就行了,如果未找到,返回NULL

ChannelMember* member = clients.Lookup(s);

if (member || PeerChannel::IsPeerConnection(s)) {

//如果发现s是注册,并且这个s并没有在服务端的注册列表中,则会用AddMember将其添加到注册列表中

if (!member) {

if (s->PathEquals(“/sign_in”)) {

clients.AddMember(s);//这里的AddMember会打印记录的客户端名,如截图的gsc@240

}

//如果客户端是等待状态,这是什么也不用做,等到有message时才进行处理

} else if (member->is_wait_request(s)) {

// no need to do anything.

socket_done = false;

//流程到这里,说明这个客户端已经在服务器注册了,并且这次收到的HTTP消息是message,不是wait,sign_out之类的

} else {

//这里找到想要通信客户端(设为B)的ChannelMember对象,如果server端没找到,则返回NULL

ChannelMember* target = clients.IsTargetedRequest(s);

if (target) {

//这里将包含客户端A SDP协议信息转送给B

member->ForwardRequestToPeer(s, target);

} else if (s->PathEquals(“/sign_out”)) {

s->Send(“200 OK”, true, “text/plain”, “”, “”);

}

}

}

}

}

当client点击connect之后,客户端给服务器发过去"/sign_in"的get请求,服务器给当前客户列表中的每个都发一遍新用户的信息,格式是"<client_name>,<client_id>,1\r\n",服务器将现有的peers列表信息以如下格式连接"<client_name>,<client_id>,if_connected?1:0\r\n"发送给新来的client.得到这些信息后客户端就会把他们显示在pees列表中。客户端每次给服务器发送消息之后都要发送一次"/wait"的get请求,目的是提供response对象,以便服务器在需要给客户端发消息时使用。当客户端双击某个peer发起连接时,会给服务器发来"/message"的post请求,请求的peer_id参数是发起方的id,to参数是要连接的peer的id,内容是sdp信息;服务器把内容转发给相应id的客户端,客户端接收到后解析sdp,得到媒体流信息(是否含音视频,音视频参数等),在本地建立媒体流通道,以便之后接收媒体数据和传给主窗体显示;完了创建本地的sdp,并发回给对方。客户端从STUN/TURN服务器获取本地地址(candidate),经由服务器中转发给对方(同样走/messgae),对方接收到后会向该地址发送消息等待回应以验证是否可连通,联通成功peerconnection就此建立完成,音视频数据就可以通过基于udp的rtp/rtcp协议在peerconnection之间传输。

客户端逻辑

客户端稍微复杂些,和server端相比,多了多媒体内容,但是WebRTC的例子非常巧妙,使用较少的代码就实现待UI的视频通信的完整例子。

Conductor是封装了windows和PeerConnection两个主要类,是该工程的核心,conductor通过CreatePeerConnectionFactory方法创建PeerConnectionFactoryInterface接口的实现对象,通过改接口创建WebRTC核心协议的PeerConnectionInterface接口对象,PeerConnectionFactoryInterface还提供了创建本地音视频功能的接口,conductor的回调通过PeerConnectionObserver接口完成。

Linux UI

linux UI层使用了GTK显示框架,将点击、输入等事件使用信号槽的机制,将界面和需要执行的动作关联起来,如点击加入会议涉及到PeerConnection创建和连接,这里clicked是Button触发的信号,而Button触发时会自动触发row-activated信号,所以下面的两个回调都会被调用到,OnClickedCallback获取用户输入的登录服务IP地址和端口号,并向服务器发起HTTP登录请求,而row-activated信号的回调PeerConnection初始化并创建和发送SDP包。代码实现上将PeerConnection和windows作为两个独立的组件,用conductor类管理起来。

g_signal_connect(button, “clicked”, G_CALLBACK(OnClickedCallback), this);

g_signal_connect(peer_list_, “row-activated”,

G_CALLBACK(OnRowActivatedCallback), this);

P2P的创建过程有些琐碎,这里罗列如下:

peer_connection_factory_ = webrtc::CreatePeerConnectionFactory(

nullptr /* network_thread */, nullptr /* worker_thread */,

nullptr /* signaling_thread */, nullptr /* default_adm */,

webrtc::CreateBuiltinAudioEncoderFactory(),

webrtc::CreateBuiltinAudioDecoderFactory(),

webrtc::CreateBuiltinVideoEncoderFactory(),

webrtc::CreateBuiltinVideoDecoderFactory(), nullptr /* audio_mixer */,

nullptr /* audio_processing */);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值