2011-02-17 30 views
1

我正在做一個簡單的testimplementation來使用PagSeguro(巴西「PayPal」),爲此我下載了他們的Python服務器來測試我的本地主機。我在Mac上工作,有一個XAMPP服務器(在我的過程中,Apache和MySQL部分)。Python中的關閉/重新啓動套接字

我的問題應該對於知道Python和套接字等的人來說非常簡單,而且我在信息搜索中發現了很多線索。然而 - 由於我在這方面的知識不足,我無法將兩個和兩個一起解決。

簡短問題:如何在程序關閉套接字之前退出一個套接字(來自終端)。 Alt - 當我想關閉套接字並停止/重新啓動服務器時,如何爲我調用Python函數。

場景: 我啓動服務器(在終端中使用#:sudo python ./PagSeguroServer.py),它工作正常,我做了一些我想做的測試。然後,我需要更改服務器的一些設置,並使其工作,我需要重新啓動服務器。我通過關閉終端窗口解決了問題,但是當我重新打開並輸入相同的命令以再次啓動服務器時,我得到了「socket.error:[Errno 48] Address already in use」。好吧,我可以看到爲什麼但不是如何修復,所以我谷歌,並找到要添加的提示

socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 

在代碼中。看着Python類,並試圖把它放在我的最佳知識(如下)。但是,並沒有解決我的問題。由於我的「搜索和謎題」似乎無法幫助我 - 我現在放棄併發布這個定製的問題!

這是服務器代碼的一部分:

class SecureHTTPServer(HTTPServer): 
    '''Servidor HTTPS com OpenSSL.''' 
    def __init__(self, server_address, HandlerClass,fpem): 
     BaseServer.__init__(self, server_address, HandlerClass) 
     ctx = SSL.Context(SSL.SSLv23_METHOD) 
     ctx.use_privatekey_file (fpem) 
     ctx.use_certificate_file(fpem) 
     self.socket = SSL.Connection(ctx, socket.socket(self.address_family, 
                 self.socket_type)) 
     self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
     self.server_bind() 
     self.server_activate() 

    .... 

def run(HandlerClass = HTTPSHandler, ServerClass = SecureHTTPServer): 
    '''Roda o servidor''' 
    server_address = ('', 443) # (address, port) 
    httpd = ServerClass(server_address, HandlerClass, fpem) 
    httpd.serve_forever() 

if __name__ == '__main__': 
    run() 

注:有一次我居然也成功地打開它 - 它是在我加入setsockopt調用,我的感覺是,插座已經關閉超時後 - 閱讀有關的地方。然而,這似乎不再發生 - 已經等待並嘗試了幾次。

編輯:最終這是我如何解決:需要殺死持有套接字的python進程(請參閱jd的回答評論),然後添加KeyboardInterrupt catch以便能夠正確關閉套接字。謝謝大家!

回答

0

如果您使用Ctrl + C關閉進程,可以嘗試在代碼中捕獲KeyboardInterrupt異常(或者更好,處理SIGINT信號),然後在退出之前徹底關閉套接字。

當然,這不會阻止你以其他方式殺死你的應用程序,並有一個陳舊的套接字,但你也可以嘗試處理這些情況。

+0

我先看到了這條評論,於是在代碼中做了更改以捕獲異常。非常感謝小費! - 但事情是,我的端口仍然從前聽,所以我不能測試它沒有先殺死這個..我怎麼能阻止它聽? – ylva

+0

我在這裏得到了一些內部幫助後意識到這是仍在運行的python進程。幫助他人:在終端中,輸入$ ps -ef查看所有進程。使用$ sudo kill -9 PID查找進程的PID編號並殺死它。 之後,我可以再次啓動服務器,並且Control + C充當魅力來阻止它!再次感謝! – ylva

+0

我很高興它幫助! :) –

0

AFAIR SO_REUSEADDR的工作原理有些不同。

但是你應該開始的 - 當你殺了你的正常工作的服務器類型

的netstat -tapdn | grep的PORT

與yoiur應用

的端口替換端口而不是您將獲得有關信息插座的狀態....

+0

我沒有得到exactely這個commant工作 - 但我測試了netstat -an(正如我在這裏看到的:http://stackoverflow.com/questions/2270343/cannot-bind-to-address-after-socket-program-崩潰),它說* .443它是偵聽。需要殺死它..你知道如何..?感謝你目前的幫助! – ylva

+0

查看我接受的答案評論我最終如何管理。感謝您給我解決問題的線索! – ylva

1

您可以創建一個函數,正確關閉套接字並將其註冊爲使用atexit.register()在程序終止時運行。見http://docs.python.org/library/atexit.html

+0

嗨,與以下相同,也會測試此版本,但首先我需要弄清楚如何阻止端口進行偵聽,以便我可以使用更改重新啓動服務器。 – ylva

+0

如果我理解正確,那麼端口會保持一秒鐘或兩分鐘以上的忙碌狀態?在這種情況下,我會確保持有套接字的進程確實停止。如果找不到進程,請嘗試使用lsof命令,例如,使用sudo lsof -P | grep「:443」。 –

+0

我決定在最後使用KeyboardInterrupt。無論如何感謝! 編輯:現在看到你的新評論,是的 - 這真的是必須被殺死的過程!謝謝! :) – ylva

0

在OSX你可以殺端口:

殺`lsof的-i:(例如8000)8000 | grep Python | cut -c8-11`

hth