讓JRTPLIB 傳送 接收資料時使用同乙個埠

2021-06-17 16:04:55 字數 1465 閱讀 9182

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...