python监听多个udp端口_Python的Socket编程过程中实现UDP端口复用的实例分享
關(guān)于端口復(fù)用
一個(gè)套接字不能同時(shí)綁定多個(gè)端口,如果客戶端想綁定端口號(hào),一定要調(diào)用發(fā)送信息函數(shù)之前綁定( bind )端口,因?yàn)樵诎l(fā)送信息函數(shù)( sendto, 或 write ),系統(tǒng)會(huì)自動(dòng)給當(dāng)前網(wǎng)絡(luò)程序分配一個(gè)隨機(jī)端口號(hào),這相當(dāng)于隨機(jī)綁定了一個(gè)端口號(hào),這里只會(huì)分配一次,以后通信就以這個(gè)隨機(jī)端口通信,我們?cè)俳壎ǘ丝谔?hào)的話,就會(huì)綁定失敗。如果我們放在發(fā)送信息函數(shù)( sendto, 或 write )之前綁定,那樣程序?qū)⒁晕覀兘壎ǖ亩丝谔?hào)發(fā)送信息,不會(huì)再隨機(jī)分配一個(gè)端口號(hào)。實(shí)際上,默認(rèn)的情況下,如果一個(gè)網(wǎng)絡(luò)應(yīng)用程序的一個(gè)套接字 綁定了一個(gè)端口,這時(shí)候,別的套接字就無(wú)法使用這個(gè)端口。那如何讓兩個(gè)套接字都能成功綁定一個(gè)端口呢?這時(shí)候就需要要到端口復(fù)用了。端口復(fù)用允許在一個(gè)應(yīng)用程序可以把 n 個(gè)套接字綁在一個(gè)端口上而不出錯(cuò)。
端口復(fù)用能在系統(tǒng)已開放的端口上進(jìn)行通訊,只對(duì)輸入的信息進(jìn)行字符匹配,不對(duì)網(wǎng)絡(luò)數(shù)據(jù)進(jìn)行任何攔截、復(fù)制類操作,所以對(duì)網(wǎng)絡(luò)數(shù)據(jù)的傳輸性能絲毫不受影響。
但要注意,建立連接后服務(wù)端程序占用極少系統(tǒng)資源,被控端不會(huì)在系統(tǒng)性能上有任何察覺,通常被后門木馬所利用。
在winsock的實(shí)現(xiàn)中,對(duì)于服務(wù)器的綁定是可以多重綁定的,在確定多重綁定使用誰(shuí)的時(shí)候,根據(jù)一條原則是誰(shuí)的指定最明確則將包遞交給誰(shuí),而且沒有權(quán)限之分,也就是說(shuō)低級(jí)權(quán)限的用戶是可以重綁定在高級(jí)權(quán)限如服務(wù)啟動(dòng)的端口上的,這是非常重大的一個(gè)安全隱患。
Python解決UDP端口復(fù)用問題
一直覺得UDP協(xié)議很簡(jiǎn)單,但是今天問題讓我感覺到網(wǎng)絡(luò)的基礎(chǔ)真是博大精深。
廢話少說(shuō),來(lái)看問題吧。由于協(xié)議的需要,我得實(shí)現(xiàn)一個(gè)UDP的客戶端和服務(wù)器端,并且從同一個(gè)端口讀寫數(shù)據(jù)。
最初不以為然,無(wú)非就是用兩個(gè)socket,一個(gè)監(jiān)聽并從這個(gè)端口讀取數(shù)據(jù)(服務(wù)器端采用了twisted),另一個(gè)向這個(gè)端口寫入數(shù)據(jù),用python實(shí)現(xiàn)只要10行左右的代碼。
?
由于要向同一個(gè)端口寫數(shù)據(jù),于是client必須有bind,但是運(yùn)行后發(fā)現(xiàn)server先bind了這個(gè)端口,client運(yùn)行時(shí)會(huì)報(bào)錯(cuò)
復(fù)制代碼 代碼如下:
error: [Errno 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
一般這種錯(cuò)誤時(shí)因?yàn)槎鄠€(gè)socket不能同時(shí)bind同一個(gè)地址
由于基礎(chǔ)不夠扎實(shí),我開始瘋狂的搜索,發(fā)現(xiàn)有人說(shuō)端口復(fù)用的問題,所謂的端口復(fù)用,是指一個(gè)套接字釋放掉一個(gè)端口后有一個(gè)wait_time,另一個(gè)套接字如果接著bind就會(huì)報(bào)錯(cuò)。雖然我的問題不完全一樣,但是我欣喜若狂的使用了。即在client bind前加上如下一句
?
但是仍然報(bào)錯(cuò):
復(fù)制代碼 代碼如下:
error: [Errno 10013] An attempt was made to access a socket in a way forbidden by its access permissions
(順便一提,還有另一個(gè)參數(shù)叫SO_REUSEPORT,即復(fù)用端口,另外有一個(gè)叫SO_EXCLUSIVEADDRUSE,即不準(zhǔn)復(fù)用該端口,其他socket的參數(shù)還有很多,可以參考winsockhttp://msdn.microsoft.com/en-us/library/aa924071.aspx或者unix下的socket)
這個(gè)10013錯(cuò)誤讓我百思不得其解,搜索一下,主要有兩種解釋,有人說(shuō)是需要提升應(yīng)用程序的權(quán)限為管理員,我用的是eclipse+pydev,提升完eclipse權(quán)限沒用,實(shí)際上還要修改python.exe的權(quán)限,方法是在這個(gè)程序上右鍵,兼容性一欄中勾上以系統(tǒng)管理員身份運(yùn)行;有人說(shuō)是跟其他程序地址或者端口沖突。但是我測(cè)試過發(fā)現(xiàn)都不行。
另外,運(yùn)行的時(shí)候發(fā)現(xiàn),twisted的服務(wù)器端一定是要在主線程中,否則會(huì)報(bào)signal一定要在主線程才能接受的錯(cuò)誤,但是twisted的reactor一運(yùn)行起來(lái)就阻塞了。
在twisted文檔中翻到,原來(lái)還有一種UDP叫做connected UDP,變態(tài)吧,所謂connected UDP,就是只能向一個(gè)地址收發(fā)數(shù)據(jù),看起來(lái)貌似可以,但是不符合可以向多個(gè)地址接收數(shù)據(jù)。
最后在一篇文章中翻到說(shuō)需要兩個(gè)端口都設(shè)置重用,于是我試著重新寫一個(gè)服務(wù)器,與之前的客戶端配合,運(yùn)行良好,完全無(wú)錯(cuò)
?
好吧,看來(lái)問題在調(diào)用twisted了,不知道他是否有這樣的設(shè)置,進(jìn)去將這部分代碼翻了一下,找不到這樣設(shè)置的參數(shù)。
?
難道說(shuō)twisted就完全不提供這樣的功能?最終在multicast中翻到這樣一段,也就是,多播的情況是支持地址復(fù)用的,動(dòng)手測(cè)起來(lái)。
?
將server端改成如下代碼,運(yùn)行通過!
?
感觸良多,底層的知識(shí)比較重要,浮沙筑高臺(tái)果然危險(xiǎn)。
總結(jié)
以上是生活随笔為你收集整理的python监听多个udp端口_Python的Socket编程过程中实现UDP端口复用的实例分享的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: node更新到最新版本_win10怎么更
- 下一篇: python sqlite3加密_sql