一、App版本(iOS為例)
單方向連接:

1.界面app已設(shè)定好,輸入房間號后,點擊join按鈕。
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,
NSData *data,
NSError *error) {
if (completionHandler) {
completionHandler(response, data, error);
}
}];
向服務(wù)器發(fā)送請求:
request:GET : turnServerUrl=https://域名/index.php?username=apprtc&key=0xc401269c75bda99dd198c568d5694730
response:{ URL:https://域名/index.php?username=apprtc&key=0xc401269c75bda99dd198c568d5694730} { status code: 200, headers {
Connection = "keep-alive";
"Content-Type" = "text/html";
Date = "Fri, 16 Jun 2017 09:10:29 GMT";
Server = "nginx/1.5.9";
"Transfer-Encoding" = Identity;
"X-Powered-By" = "PHP/5.5.9-1ubuntu4.21";
} }
data:
iceServers =? ? (
{
credential = "yjp0ArWpl1s8vOYegRGpYRU/XzU=";
ttl = 86400;
urls =? ? ? ? ? ? (
"turn:域名:3478?transport=tcp",
"turn:域名:3479?transport=udp",
"turn:域名:3479?transport=tcp"
);
username = "1497605539:";
}
);
request:POST: url =https://域名/join/123456
response:{ URL:https://域名/join/123456} { status code: 200, headers {
"Cache-Control" = "no-cache";
Connection = "keep-alive";
"Content-Length" = 1230;
"Content-Type" = "text/html; charset=utf-8";
Date = "Fri, 16 Jun 2017 09:38:42 GMT";
Server = "nginx/1.5.9";
} }
data:
params? ? Object
pc_config? ? "{\"rtcpMuxPolicy\": \"require…dlePolicy\": \"max-bundle\"}"
room_id? ? "622620833"
turn_url? ? "https://域名/index…username=27212903&key=apprtc"
error_messages? ? []
wss_post_url? ? "https:/域名:4432"
callstats_params? ? "{\"appId\": \"none\", \"appSecret\": \"none\"}"
include_rtstats_js? ? ""
version_info? ? "{\"branch\": \"master\", \"gi…Mar 6 07:49:29 2017 +0100\"}"
messages? ? []
ice_server_transports? ? ""
warning_messages? ? []
media_constraints? ? "{\"video\": true, \"audio\": true}"
is_loopback? ? "false"
pc_constraints? ? "{\"optional\": []}"
room_link? ? "http://域名/r/roomID"
offer_options? ? "{}"
is_initiator? ? "true"
ice_server_url? ? "https://域名/v1alpha/iceconfig?key=none"
include_loopback_js? ? ""
client_id? ? "27212903"
turn_server_override? ? []
bypass_join_confirmation? ? "false"
result? ? “SUCCESS"
2.上面返回的信息中有wss_url,”wss://域名:4432/ws",wss_post_url“https://域名:4432”,即是websocketUrl,初始化websocket,注冊信令,創(chuàng)建主機tcp? /ip端口可讀寫流。
3.創(chuàng)建peerconnection ,創(chuàng)建LocalMediaStream:videoTrack,audioTrack.發(fā)送offer.
4.通過websocket輸入輸出
outPutStream: outPutBuffer:
GET /ws HTTP/1.1
Host:域名:4432
Sec-WebSocket-Version:13
Upgrade:websocket
Dec-WebSocket-Key:tu1zu……==
Connection:Upgrade Origin:https://域名:4432
inputStream:readBuffer
HTTP1.1? 101 Switching Protocols
Upgrade? "websocket"
Connection? ? "Upgrade"
Sec-WebSocket-Accept? ? "geUmCmY/h7EFD1/qjbtzyfy1g04="
服務(wù)器返回上面代碼,表示websocket協(xié)議請求成功,狀態(tài)碼101表示服務(wù)器客戶端升級協(xié)議的請求正在進行協(xié)議切換,以后的通信就是websocket協(xié)議,后續(xù)就可以tcp通訊了。
5.websocket注冊成功:
log:WebSocket connection opened.
Registering on WSS for rid:123456 cid:09876543
outPutStream:outPutBuffer:
message = {
"cmd" : "register",
"roomid" : "123456",
"clientid" : "09876543"
}
6.log :Signaling state changed: 1:LocalOffer
ICE gathering state changed: 1:Checking
調(diào)用PTCPeerConection方法實現(xiàn)
7.SDP
log:
C->RS POST: {"type":"offer","sdp":"v=0\r\no=- 7930074291607742461 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE audio video\r\na=msid-semantic: WMS ARDAMS\r\nm=audio 9 UDP\/TLS\/RTP\/SAVPF 111 103 104 9 102 0 8 106 105 13 127 126\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:9z7jtEySOjadK2L3\r\na=ice-pwd:P1FSuJPZnkh3t3OU+JWzY3tn\r\na=fingerprint:sha-256 CB:94:1B:E8:AB:B0:D6:EC:BC:B6:54:52:87:17:FC:8D:B4:76:3A:FA:6C:96:D7:BE:32:D7:BD:33:26:5D:20:55\r\na=setup:actpass\r\na=mid:audio\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=extmap:3 http:\/\/www.webrtc.org\/experiments\/rtp-hdrext\/abs-send-time\r\na=sendrecv\r\na=rtcp-mux\r\na=rtpmap:111 opus\/48000\/2\r\na=fmtp:111 minptime=10; useinbandfec=1\r\na=rtpmap:103 ISAC\/16000\r\na=rtpmap:104 ISAC\/32000\r\na=rtpmap:9 G722\/8000\r\na=rtpmap:102 ILBC\/8000\r\na=rtpmap:0 PCMU\/8000\r\na=rtpmap:8 PCMA\/8000\r\na=rtpmap:106 CN\/32000\r\na=rtpmap:105 CN\/16000\r\na=rtpmap:13 CN\/8000\r\na=rtpmap:127 red\/8000\r\na=rtpmap:126 telephone-event\/8000\r\na=maxptime:60\r\na=ssrc:282299390 cname:dwTJJogpUnEjR9By\r\na=ssrc:282299390 msid:ARDAMS ARDAMSa0\r\na=ssrc:282299390 mslabel:ARDAMS\r\na=ssrc:282299390 label:ARDAMSa0\r\nm=video 9 UDP\/TLS\/RTP\/SAVPF 100 101 116 117 96\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:9z7jtEySOjadK2L3\r\na=ice-pwd:P1FSuJPZnkh3t3OU+JWzY3tn\r\na=fingerprint:sha-256 CB:94:1B:E8:AB:B0:D6:EC:BC:B6:54:52:87:17:FC:8D:B4:76:3A:FA:6C:96:D7:BE:32:D7:BD:33:26:5D:20:55\r\na=setup:actpass\r\na=mid:video\r\na=extmap:2 urn:ietf:params:rtp-hdrext:toffset\r\na=extmap:3 http:\/\/www.webrtc.org\/experiments\/rtp-hdrext\/abs-send-time\r\na=extmap:4 urn:3gpp:video-orientation\r\na=sendrecv\r\na=rtcp-mux\r\na=rtpmap:100 VP8\/90000\r\na=rtcp-fb:100 ccm fir\r\na=rtcp-fb:100 nack\r\na=rtcp-fb:100 nack pli\r\na=rtcp-fb:100 goog-remb\r\na=rtpmap:101 VP9\/90000\r\na=rtcp-fb:101 ccm fir\r\na=rtcp-fb:101 nack\r\na=rtcp-fb:101 nack pli\r\na=rtcp-fb:101 goog-remb\r\na=rtpmap:116 red\/90000\r\na=rtpmap:117 ulpfec\/90000\r\na=rtpmap:96 rtx\/90000\r\na=fmtp:96 apt=100\r\na=ssrc-group:FID 797147928 458665663\r\na=ssrc:797147928 cname:dwTJJogpUnEjR9By\r\na=ssrc:797147928 msid:ARDAMS ARDAMSv0\r\na=ssrc:797147928 mslabel:ARDAMS\r\na=ssrc:797147928 label:ARDAMSv0\r\na=ssrc:458665663 cname:dwTJJogpUnEjR9By\r\na=ssrc:458665663 msid:ARDAMS ARDAMSv0\r\na=ssrc:458665663 mslabel:ARDAMS\r\na=ssrc:458665663 label:ARDAMSv0\r\n”}
[self sendSignalingMessage:sdp]
[self sendSignalingMessageToRoomServer:sdp completionHandler:nil];
sdp:
v=0
o=- 631685190248252292 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video
a=msid-semantic: WMS ARDAMS
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 102 0 8 106 105 13 127 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:ktg6AGYFl6ibNPGY
a=ice-pwd:ZL5KQbLLCNZkDIy0Zt0DXWZ2
a=fingerprint:sha-256 DF:4B:02:9E:4E:78:98:75:BD:E8:13:B4:FD:E5:72:EE:24:B5:36:43:73:6E:A1:3C:4C:13:FD:7A:15:30:5F:E8
a=setup:actpass
a=mid:audio
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:3http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=sendrecv
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10; useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:102 ILBC/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:127 red/8000
a=rtpmap:126 telephone-event/8000
a=maxptime:60
a=ssrc:1330996120 cname:BeTH+Ahwn2YbXhAJ
a=ssrc:1330996120 msid:ARDAMS ARDAMSa0
a=ssrc:1330996120 mslabel:ARDAMS
a=ssrc:1330996120 label:ARDAMSa0
m=video 9 UDP/TLS/RTP/SAVPF 100 101 116 117 96
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:ktg6AGYFl6ibNPGY
a=ice-pwd:ZL5KQbLLCNZkDIy0Zt0DXWZ2
a=fingerprint:sha-256 DF:4B:02:9E:4E:78:98:75:BD:E8:13:B4:FD:E5:72:EE:24:B5:36:43:73:6E:A1:3C:4C:13:FD:7A:15:30:5F:E8
a=setup:actpass
a=mid:video
a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
a=extmap:3http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:4 urn:3gpp:video-orientation
a=sendrecv
a=rtcp-mux
a=rtpmap:100 VP8/90000
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 goog-remb
a=rtpmap:101 VP9/90000
a=rtcp-fb:101 ccm fir
a=rtcp-fb:101 nack
a=rtcp-fb:101 nack pli
a=rtcp-fb:101 goog-remb
a=rtpmap:116 red/90000
a=rtpmap:117 ulpfec/90000
a=rtpmap:96 rtx/90000
a=fmtp:96 apt=100
a=ssrc-group:FID 3011579612 365513713
a=ssrc:3011579612 cname:BeTH+Ahwn2YbXhAJ
a=ssrc:3011579612 msid:ARDAMS ARDAMSv0
a=ssrc:3011579612 mslabel:ARDAMS
a=ssrc:3011579612 label:ARDAMSv0
a=ssrc:365513713 cname:BeTH+Ahwn2YbXhAJ
a=ssrc:365513713 msid:ARDAMS ARDAMSv0
a=ssrc:365513713 mslabel:ARDAMS
a=ssrc:365513713 label:ARDAMSv0
request:request.HTTPMethod = POST: url =https://域名/message/45677/60574066
A. request.HTTPBody =sdp;
block函數(shù)為nil,沒有設(shè)置返回值
B.request.HTTPBody =icecandidate;
其中icecandidate 從[peerConnection? gotICECandidate]獲取到的。
log :{
"label" : 0,
"id" : "audio",
"candidate" : "candidate:3672176605 1 udp 2122260223 192.168.153.194 55122 typ host generation 0",
"type" : "candidate"
}
{"label" : 1,
"id" : "video",
"candidate" : "candidate:3005921308 1 udp 1686052607 1.85.223.111 10107 typ srflx raddr 192.168.153.194 rport 65478 generation 0",
"type" : "candidate"
}
response:
{ URL:https://域名/message/46789/02181168} { status code: 200, headers {
"Cache-Control" = "no-cache";
Connection = "keep-alive";
"Content-Length" = 21;
"Content-Type" = "text/html; charset=utf-8";
Date = "Fri, 16 Jun 2017 10:50:36 GMT";
Server = "nginx/1.5.9";
} }
data:result :SUCCESS
房間服務(wù)器收到 /message/消息后將request.HTTPBody的信息sdp,icecandidate發(fā)送給信令服務(wù)器。
8.掛斷
request :POST:url =https://域名/leave/123456/09876543
response:{ URL:https://域名/leave/123456/09876543}{ status code: 200, headers {
"Cache-Control" = "no-cache";
Connection = "keep-alive";
"Content-Type" = "text/html; charset=utf-8";
Date = "Fri, 16 Jun 2017 09:38:42 GMT";
Server = "nginx/1.5.9";
} }
data :0 bytes
outPutStream:outPutBuffer:
message = {
"cmd" : "send",
"msg":"{type:"bye"}"
}
websocket:
request :DELETE:url =https://域名:4432/123456/09876543
request.HTTPMethod:"Delete"
request.HTTPBody:nil
response:{ URL:https://域名:4432/123456/09876543}{ status code: 200, headers {
"Acess-Control-Allow-Methods" = "POST,DELETE";
"Acess-Control-Allow-Origin"="*"
"Content-Length" = 3;
Connection = "keep-alive";
"Content-Type" = "text/html; charset=utf-8";
Date = "Fri, 16 Jun 2017 09:38:42 GMT";
Server = "nginx/1.5.9";
} }
data :OK
加入到同一個房間
房間的最大人數(shù)是在房間服務(wù)器room.go中設(shè)定,默認(rèn)為2個人。client A 注冊房間號,向websocket發(fā)送
message = {
"cmd" : "register",
"roomid" : "123456",
"clientid" : "09876543"
}
信息,clientID 是隨機生成的,當(dāng)client A和client B進入同一個房間時,websocket打開client A 和client B的ReadWriteClose接口,會相互發(fā)送對方的msg
獲取到對方的sdp,answer和icecandidate
inputStream:readBuffer
{"type":"answer","sdp":"v=0\r\no=- 2842181041571733368 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE audio video\r\na=msid-semantic: WMS ARDAMS\r\nm=audio 9 UDP\/TLS\/RTP\/SAVPF 111 103 104 9 102 0 8 106 105 13 126\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:5EBa\r\na=ice-pwd:+BOWo0ZqtrGNvmtWWCtHX0QC\r\na=ice-options:renomination\r\na=fingerprint:sha-256 E5:06:2E:37:E8:13:0C:45:B3:AC:28:92:71:5B:60:32:6D:E8:B7:D5:E2:96:B0:E5:17:B6:92:33:6A:1C:DF:8E\r\na=setup:active\r\na=mid:audio\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=sendrecv\r\na=rtcp-mux\r\na=rtpmap:111 opus\/48000\/2\r\na=fmtp:111 minptime=10;useinbandfec=1\r\na=rtpmap:103 ISAC\/16000\r\na=rtpmap:104 ISAC\/32000\r\na=rtpmap:9 G722\/8000\r\na=rtpmap:102 ILBC\/8000\r\na=rtpmap:0 PCMU\/8000\r\na=rtpmap:8 PCMA\/8000\r\na=rtpmap:106 CN\/32000\r\na=rtpmap:105 CN\/16000\r\na=rtpmap:13 CN\/8000\r\na=rtpmap:126 telephone-event\/8000\r\na=ssrc:1892460007 cname:DBqx+KdFlQmMiVm6\r\na=ssrc:1892460007 msid:ARDAMS ARDAMSa0\r\na=ssrc:1892460007 mslabel:ARDAMS\r\na=ssrc:1892460007 label:ARDAMSa0\r\nm=video 9 UDP\/TLS\/RTP\/SAVPF 100 101 116 117 96\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:5EBa\r\na=ice-pwd:+BOWo0ZqtrGNvmtWWCtHX0QC\r\na=ice-options:renomination\r\na=fingerprint:sha-256 E5:06:2E:37:E8:13:0C:45:B3:AC:28:92:71:5B:60:32:6D:E8:B7:D5:E2:96:B0:E5:17:B6:92:33:6A:1C:DF:8E\r\na=setup:active\r\na=mid:video\r\na=extmap:2 urn:ietf:params:rtp-hdrext:toffset\r\na=extmap:3 http:\/\/www.webrtc.org\/experiments\/rtp-hdrext\/abs-send-time\r\na=extmap:4 urn:3gpp:video-orientation\r\na=sendrecv\r\na=rtcp-mux\r\na=rtpmap:100 VP8\/90000\r\na=rtcp-fb:100 ccm fir\r\na=rtcp-fb:100 nack\r\na=rtcp-fb:100 nack pli\r\na=rtcp-fb:100 goog-remb\r\na=rtpmap:101 VP9\/90000\r\na=rtcp-fb:101 ccm fir\r\na=rtcp-fb:101 nack\r\na=rtcp-fb:101 nack pli\r\na=rtcp-fb:101 goog-remb\r\na=rtpmap:116 red\/90000\r\na=rtpmap:117 ulpfec\/90000\r\na=rtpmap:96 rtx\/90000\r\na=fmtp:96 apt=100\r\na=ssrc-group:FID 3263650902 1527749129\r\na=ssrc:3263650902 cname:DBqx+KdFlQmMiVm6\r\na=ssrc:3263650902 msid:ARDAMS ARDAMSv0\r\na=ssrc:3263650902 mslabel:ARDAMS\r\na=ssrc:3263650902 label:ARDAMSv0\r\na=ssrc:1527749129 cname:DBqx+KdFlQmMiVm6\r\na=ssrc:1527749129 msid:ARDAMS ARDAMSv0\r\na=ssrc:1527749129 mslabel:ARDAMS\r\na=ssrc:1527749129 label:ARDAMSv0\r\n"}
{"type":"candidate","label":0,"id":"audio","candidate":"candidate:1300829926
1 udp 2122260223 192.168.153.186 36349 typ host generation 0 ufrag Xe0D
network-id 3 network-cost 10"}
二、Web網(wǎng)頁版
1.獲取網(wǎng)頁界面信息
GEThttps://域名/[HTTP/1.1 200 OK 32ms]
response:網(wǎng)頁界面信息html
GEThttps://域名/css/main.css[HTTP/1.1 304 Not Modified 23ms]
main.css中的內(nèi)容如網(wǎng)頁的長寬、顏色等
GEThttps://域名/callstats/callstats.min.js[HTTP/1.1 304 Not Modified 44ms]
GEThttps://域名/callstats/sha.js[HTTP/1.1 304 Not Modified 65ms]
sha.js:加密信息
GEThttps://域名/callstats/socket.io.js[HTTP/1.1 304 Not Modified 65ms]
socket.io.js:websocket protocol
GEThttps://域名/js/apprtc.debug.js[HTTP/1.1 304 Not Modified 70ms]
GEThttps://www.google-analytics.com/analytics.js[HTTP/2.0 304 Not Modified 62ms]
GEThttps://www.google-analytics.com/r/collect[HTTP/2.0 200 OK 73ms]
2.輸入房間號,點擊join按鈕,加入房間
POST XHRhttps://域名/join/040075152[HTTP/1.1 200 OK 35ms]
3.連接websocket協(xié)議
GEThttps://域名:4432/ws[HTTP/1.1 101 Switching Protocols 49ms]
4.給服務(wù)器發(fā)送sdp和icecandidate信息,房間服務(wù)器轉(zhuǎn)將信息轉(zhuǎn)發(fā)給信令服務(wù)器
POST XHRhttps://域名/message/040075152/13888651[HTTP/1.1 200 OK 44ms]
POST XHRhttps://域名/message/040075152/13888651[HTTP/1.1 200 OK 36ms]
POST XHRhttps://域名/message/040075152/13888651[HTTP/1.1 200 OK 46ms]
POST XHRhttps://域名/message/040075152/13888651[HTTP/1.1 200 OK 51ms]
POST XHRhttps://域名/message/040075152/13888651[HTTP/1.1 200 OK 42ms]
POST XHRhttps://域名/message/040075152/13888651[HTTP/1.1 200 OK 29ms]
POST XHRhttps://域名/message/040075152/13888651[HTTP/1.1 200 OK 30ms]
POST XHRhttps://域名/message/040075152/13888651[HTTP/1.1 200 OK 31ms]
POST XHRhttps://域名/message/040075152/13888651[HTTP/1.1 200 OK 32ms]
response:result SUCCESS