2011-05-03 35 views
30

我有一個Python應用程序,它打開一個簡單的TCP套接字與另一個主機上的另一個Python應用程序通信。有時程序會出錯,或者我會直接殺死它,並且在任何一種情況下,套接字可能會在未知的時間保持打開狀態。如何關閉被死程序打開的插槽?

下一次我去運行程序我得到這個錯誤:

socket.error: [Errno 98] Address already in use 

現在的程序總是使用相同的端口,所以它看起來好像它仍然是開放的。我查了一下,很確定這個程序沒有在後臺運行,但我的地址仍在使用中。那麼,我該如何手動(或以其他方式)關閉套接字/地址,以便我的程序可以立即重新使用它?

更新

基於邁克的回答我檢查了socket(7)頁,看着SO_REUSEADDR:

SO_REUSEADDR 
    Indicates that the rules used in validating addresses supplied in a bind(2) call should 
    allow reuse of local addresses. For AF_INET sockets this means that a socket may bind, 
    except when there is an active listening socket bound to the address. When the listen‐ 
    ing socket is bound to INADDR_ANY with a specific port then it is not possible to bind 
    to this port for any local address. Argument is an integer boolean flag. 
+0

任何反對將此轉移到SO?它最終是一個完全的編程問題,所以它可能更有意義 – 2011-05-03 16:03:45

+0

一點都不,我只在這裏發佈這個,因爲我正在考慮關閉套接字的Linux命令,我同意它的編程材料。也許標題可能會改變,以反映它是一個Python程序。 – 2011-05-03 18:57:26

+0

@Mr。 Shickadance遷移了,如果你覺得有必要,你必須重新標題。 – xenoterracide 2011-05-03 20:18:23

回答

31

假設你的插座被命名爲s ......你需要設置socket.SO_REUSEADDR在服務器的socket之前綁定到一個接口...這將允許您立即重新啓動一個TCP服務器...

s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
s.bind((ADDR, PORT)) 
+0

我相信你的意思是' setsockopt',我嘗試過但仍然沒有運氣。我會在進行更多測試後再報告。 – 2011-05-03 15:12:03

+0

@Mr。 Shickadance,是的''setsockopt()'...我輸錯了 – 2011-05-03 15:15:59

+0

我錯了,這確實解決了這個問題...這就是爲什麼我提到更多的測試!在我進行測試之前,我沒有推新的修改過的代碼(不知道我是如何忘記的)。謝謝! – 2011-05-03 15:29:29

10

您可能想嘗試使用Twisted進行聯網。 Mike給出了正確的低級答案,SO_REUSEADDR,但是他沒有提到這不是在Windows上設置的很好選擇。這是Twisted自動處理的事情。這種無聊的底層細節有很多很多其他的例子,當你直接使用socket模塊時你必須注意,但如果你使用像Twisted這樣的更高級別的庫,你可能會忘記它。

+2

'這不是一個很好的選擇在Windows上設置'。爲什麼不? – EJP 2011-05-04 10:34:02

+5

在Windows上,REUSEADDR允許進程接管另一個正在運行**進程的監聽端口。 – 2011-05-04 11:17:36

+1

這是從unix.stackexchange.com遷移出來的,所以Windows可能不是一個大問題。無論如何,好點+ 1 – 2013-02-18 01:25:13

2

你在混淆套接字,連接和端口。套接字是連接的端點,它又是5元組{協議,本地ip,本地端口,遠程ip,遠程端口}。殺死的程序的套接字已被操作系統關閉,並且與連接相同。連接的唯一遺蹟是對等體的套接字和對等主機上的對應端口。所以你真正應該問的是如何重用本地的端口根據其他答案,答案是SO_REUSEADDR。

相關問題