轉自: http://www.cnblogs.com/MikeZhang/archive/2012/10/29/rtspTcpClient_DSS_20121029.html
由於某種需求,工作中需要自己要開發RTSP客戶端模擬器……這里以DarwinStreamingServer(簡稱DSS)為例進行演示,把思路記錄下來,算是開發了一個測試工具,也方便我以后查閱。在我之前的文章(http://www.cnblogs.com/MikeZhang/archive/2012/09/16/RTSPoverTCPUDP20120916.html )中介紹過怎樣通過TCP的方式來訪問DSS,在那個實例中,我用的是VLC作為客戶端,通過命令行參數進行調用的。
一、通信端口分析
首先通過抓包分析確定數據通信端口。
RTSP數據包截圖:
RTP數據包截圖:
RTCP數據包截圖:
由圖可知,在以TCP方式訪問DSS時,RTSP數據、RTP數據和RTCP數據都是通過554端口進行傳輸的,所以DSS服務器只通過554端口和客戶端通信。
二、通信過程分析
OPTIONS :查詢到服務器所提供的方法;
DESCRIBE :得到會話描述信息(SDP);
SETUP :提醒服務器建立會話,並確定傳輸模式;
PLAY :客戶端發送播放請求;
TEARDOWN :客戶端發起關閉請求;
當然中間還有RTP和RTCP的交互,這里就不敘述了。
三、模擬器實現
1、建立鏈接
1 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 2 s.connect((m_Vars["defaultServerIp"],m_Vars["defaultServerPort"]))
2、查詢服務器所提供的方法
向服務器發送OPTIONS請求,得到服務器所提供的方法。
1 s.send(genmsg_OPTIONS(m_Vars["defaultTestUrl"],seq,m_Vars["defaultUserAgent"])) 2 print s.recv(m_Vars["bufLen"])
3、得到會話描述信息
向服務器發送DESCRIBE請求,得到SDP
1 s.send(genmsg_DESCRIBE(m_Vars["defaultTestUrl"],seq,m_Vars["defaultUserAgent"])) 2 msg1 = s.recv(m_Vars["bufLen"]) 3 print msg1
4、提醒服務器建立會話,並確定傳輸模式
向服務器發送SETUP請求,通知服務器產生session,並和服務器確定傳輸模式等。
1 s.send(genmsg_SETUP(m_Vars["defaultTestUrl"] + "/trackID=3",seq,m_Vars["defaultUserAgent"])) 2 msg1 = s.recv(m_Vars["bufLen"]) 3 print msg1 4 seq = seq + 1 5 6 sessionId = decodeMsg(msg1)['Session'] 7 8 s.send(genmsg_SETUP2(m_Vars["defaultTestUrl"] + "/trackID=4",seq,m_Vars["defaultUserAgent"],sessionId)) 9 msg1 = s.recv(m_Vars["bufLen"]) 10 print msg1
5、客戶端發起播放請求
向服務器發送PLAY請求,通知服務器發送RTP數據。
1 s.send(genmsg_PLAY(m_Vars["defaultTestUrl"] + "/",seq,m_Vars["defaultUserAgent"],sessionId)) 2 msg1 = s.recv(m_Vars["bufLen"]) 3 print msg1
客戶端接收RTP數據
1 while True : 2 msgRcv = s.recv(m_Vars["bufLen"]) 3 if 0 == len(msgRcv) : break 4 print len(msgRcv)
6、客戶端發起關閉請求
客戶端向服務器發送TREADOWN請求,通知服務器關閉。
1 s.send(genmsg_TEARDOWN(m_Vars["defaultTestUrl"] + "/",seq,m_Vars["defaultUserAgent"],sessionId)) 2 msg1 = s.recv(m_Vars["bufLen"]) 3 print msg1
完整代碼:https://gist.github.com/3974202