jrtplib在傳送資料和接收資料時使用的不是同乙個port,這就可能導致無法穿透內網,我的想法大致如下:
假設a的rtp使用埠1000,則起對應的rtcp埠必定為1001,在初始化rtp信令後,jrtplib會隨機使用另外乙個埠3333來傳送rtp資料,1000埠是用來接收rtp資料的,1001接收rtcp包。
假設b的rtp使用埠2000,則起對應的rtcp埠必定為2001,在初始化rtp信令後,jrtplib會隨機使用另外乙個埠4444來傳送rtp資料,2000埠是用來接收rtp資料的,2001接收rtcp包。
又假設a,b均在nat後,經nat轉換後,利用stun協議,a開始向b發包,b也向a發包,由於nat的存在,b發給a的包並不是a發出去的目的位址埠發過來的,目的埠只受資料不發資料(a將資料報發給b的rtp接收埠後,nat a就只接收b的這個rtp埠發過來的資料,對於b用來傳送資料的埠而言,是不請自到的),因此nat a會丟棄b發過來的包,同理nat b也會丟棄a發過來的包。
這樣一來,為了能udp punch hole,a,b就必須再往對方用來傳送資料的埠打乙個洞,以便欺騙nat,但udp是不可靠的,而nat影射也有時間限制,要保證nat的影射關係不變就的定時打洞給對方,個人感覺這種方法不是很好。
經過檢視jrtplib原始碼,它的create()函式裡是這麼寫的
addr.sin_family = af_inet;
addr.sin_port = htons(0); //就是這裡使用隨機埠
addr.sin_addr.s_addr = htonl(0);
if (bind(sendsock,(struct sockaddr *)&addr,sizeof(struct sockaddr)) != 0)
socklen = sizeof(struct sockaddr_in);
if (getsockname(sendsock,(struct sockaddr *)&addr,&socklen) != 0)
sendport = ntohs(addr.sin_port);//這裡是傳送資料的埠
很明顯,它用的是隨機埠,bind成功後再查詢這個埠的,在rtpsession裡用於獲取傳送埠的函式getsendport()直接返回了這個sendport,如下:
int getsendport()
為此,我只好修改jrtplibv2.9的原始碼了,在rtpconnection.cpp裡,將傳送資料的sendto語句裡的socket都換成rtpsocket,讓他使用bind在rtp埠的socket即可,同時刪除sendsocket,並將getsendport()直接返回portbase。經過修改,傳送/接收資料時就只有rtp和rtcp埠了,而且收發資料都通過rtp繫結的那個埠進行。
基於jrtplib的rtp資料傳送
1.1 初始化 在使用jrtplib進行實時流 資料傳輸之前,首先應該生成rtpsession類的乙個例項來表示此次rtp會話,然後呼叫create 方法來對其進行初始化操作。rtpsession類的create 方法只有乙個引數,用來指明此次rtp會話所採用的埠號。1給出了乙個最簡單的初始化框架,...
基於jrtplib的rtp資料傳送
1.1 初始化 在使用jrtplib進行實時流 資料傳輸之前,首先應該生成rtpsession類的乙個例項來表示此次rtp會話,然後呼叫create 方法來對其進行初始化操作。rtpsession類的create 方法只有乙個引數,用來指明此次rtp會話所採用的埠號。1給出了乙個最簡單的初始化框架,...
傳送與接收float資料
在寫硬體程式的時候,經常遇到要通過串列埠 can匯流排等傳送float型別的資料。由於mcu是以單個位元組為單位來傳送資料的,所以在遇到要傳送float,double這種占用多個位元組的資料型別的資料時,如果對指標的概念理解不到位,就很難實現。以float型別的資料為例,我的方法如下 傳送 void...