UdpClient的Connect究竟做了什麼

2022-07-09 18:06:19 字數 1380 閱讀 5243

最近在寫乙個音訊通訊的系統,因為需要還要處理其他事件,所以就自己設計底層的通訊協議,用了不少底層的socket程式設計(.net framework),搞清楚了不少細節問題。

先做一些鋪墊工作。音訊系統伺服器需要給所有的客戶端傳送音訊。伺服器端要記錄下連線的客戶端的ipendpoint(也就是ip+埠號),然後會對所有連線的客戶端**。因為客戶端很可能是在nat後的,所以不可能直接用向某個位址的udp客戶端傳送連線。所以客戶端需要把第一條訊息傳送給伺服器端,nat伺服器就會開啟乙個口,允許伺服器端向這個客戶端傳送包(這就是最簡單的所謂的「udp打洞」技術)。當然這個埠不會一直保留,一般不用的話很快就會被關閉。不過傳輸實時音訊一般都會連續使用的,所以不用太擔心這個問題。

所以客戶端先要向伺服器傳送一條訊息,伺服器端看到這是要求接受的訊息後,就會把獲得的ipendpoint加到**列表中。伺服器端的監聽udpclient要bind到乙個埠,它只需要考慮接受訊息。另乙個udpclient來傳送訊息,而這個不指定傳送目標也沒有繫結到埠的udpclient,需要在傳送時指定訊息目標,或者用connect方法,來指定某個預設目標。伺服器端因為要向不同的目標傳送,所以不用connect。

但是客戶端的udpclient卻需要首先作為傳送端,然後再作為接受端。因為在發起第乙個傳送的時候,作業系統會自動選取乙個埠號,因此我們就希望客戶端能在此監聽。但是客戶端傳送時只跟伺服器的某個ipendpoint通訊,所以一開始我就用connect連線到伺服器的ipendpoint。幾乎所有的文件都說,connect基本不做什麼事情,它只是設定send的預設接收端,免去每次傳送都指定接收端的麻煩。但是connect其實還做了一件事,導致客戶端接收不到伺服器傳送過來的訊息。是什麼呢?

因為connect把該udpclient所能接受的****限制為所連線的接受端。但是伺服器端的傳送卻是另乙個udpclient執行的,它的埠號是由系統隨機分配的,而不是監聽訊息的udpclient。所以客戶端的udpclient就不能接受到這個訊息。所以這種需要連線乙個udpclient,卻需要接受另乙個udpclient訊息的情況,就不能使用connect了。解決的辦法是直接使用sendto(socket方法)或者udpclient指定目的的send方法的過載。

但是能夠用同乙個正在receive的udpclient同時傳送資料嗎?按說應該可以,但是沒有試驗過,有經驗的大牛直接告訴我得了。而且對於使用了執行緒的伺服器來說(使用.net的非同步程式設計模型潛在使用了執行緒池),用乙個udpclient來做所有的工作,總是擔心會出現併發訪問問題,或者出現併發導致的效率損失。所以為了保險起見,還是各做各的事比較好。

如果在區域網,或者以後大家都用ipv6,就沒有這些複雜的問題,直接客戶端開乙個埠監聽就行了。伺服器只要知道ip,就可以向預設的埠傳送訊息。多麼美好的景象!

Python中MySQLdb的connect的用法

mysqldb模組是python連線mysql資料庫的乙個模組,在操作mysql資料庫是經常使用,在連線資料庫時connect是最常用的一種方法,這個方法有好多引數,總結了一下,主要有一下幾種 connect 方法用於連線資料庫,返回乙個資料庫連線物件。如果要連線乙個位於www.gyyx.com伺服...

Python中MySQLdb的connect的用法

mysqldb模組是python連線mysql資料庫的乙個模組,在操作mysql資料庫是經常使用,在連線資料庫時connect是最常用的一種方法,這個方法有好多引數,總結了一下,主要有一下幾種 connect 方法用於連線資料庫,返回乙個資料庫連線物件。如果要連線乙個位於www.gyyx.com伺服...

react中使用hooks替代connect

使用hooks代替connect 在react中的connect的使用 import react,from react import from react redux import from antd import from react redux import from store discove...