2009-08-20 39 views
1

Pyzor使用UDP/IP作爲通信協議。我們最近將公共服務器切換到一臺新機器上,並開始獲取許多超時報告。我發現如果將查詢的eth0:1 IP更改爲eth0,我可以解決問題。UDP服務是否必須從連接的IP地址進行響應?

我可以重現此問題,以簡單的例子:

這是服務器代碼:

#! /usr/bin/env python 

import SocketServer 

class RequestHandler(SocketServer.DatagramRequestHandler): 
    def handle(self): 
     print self.packet 
     self.wfile.write("Pong") 

s = SocketServer.UDPServer(("0.0.0.0", 24440), RequestHandler) 
s.serve_forever() 

這是客戶機代碼(188.40.77.206eth0188.40.77.236是相同的服務器,但是eth0:1。 ):

>>> import socket 
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
>>> s.sendto('ping', 0, ("188.40.77.206", 24440)) 
4 
>>> s.recvfrom(1024) 
('Pong', ('188.40.77.206', 24440)) 
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
>>> s.sendto('ping', 0, ("188.40.77.236", 24440)) 
4 
>>> s.recvfrom(1024) 
[never gets anything] 

的服務器獲取在這兩種情況下的「ping」分組(並且因此發送「PON g「包)。

奇怪的是,這確實工作從一些地方(即我會得到來自兩個IP的響應)。例如,它可以從188.40.37.137(相同的網絡/數據中心,不同的服務器)運行,但也可以從89.18.189.160(不同的數據中心)運行。在這些情況下,recvfrom響應確實具有IP地址eth0,而不是已連接的IP地址。

這只是UDP的規則?這是否是PythonUDPServer類的問題/限制?這是我做錯了什麼嗎?有沒有什麼辦法可以讓我從簡單地連接到eth0 IP(或聽取特定的IP而不是0.0.0.0)這個工作?

回答

3

我遇到了這個TFTP服務器。我的服務器有兩個IP地址面對同一個網絡。因爲UDP是無連接的,所以在這種情況下,可能會出現IP地址未按預期設置的問題。我的順序是:

  1. 客戶端發送初始數據包到服務器,在一個特定的IP地址
  2. Server讀取從傳入數據包中的客戶端的源地址,併發送響應。
    1. 然而,在響應,服務器的「源地址」是根據路由表設置,並且它被設置爲其他 IP地址。
    2. 控制服務器的「源」IP地址是不可能的,因爲操作系統沒有告訴我們請求通過哪個IP地址。
  3. 客戶端從「其他」IP地址獲得響應,並拒絕它。

在我的情況下,解決方案是專門綁定TFTP服務器到我想聽的IP地址,而不是綁定到所有接口。

我發現了一些可能與Linux man page for tftpd(TFTP服務器)相關的文本。那就是:

Unfortunately, on multi-homed systems, it is impossible for tftpd to 
determine the address on which a packet was received. As a result, tftpd 
uses two different mechanisms to guess the best source address to use for 
replies. If the socket that inetd(8) passed to tftpd is bound to a par‐ 
ticular address, tftpd uses that address for replies. Otherwise, tftpd 
uses ‘‘UDP connect’’ to let the kernel choose the reply address based on 
the destination of the replies and the routing tables. This means that 
most setups will work transparently, while in cases where the reply 
address must be fixed, the virtual hosting feature of inetd(8) can be 
used to ensure that replies go out from the correct address. These con‐ 
siderations are important, because most tftp clients will reject reply 
packets that appear to come from an unexpected address. 

this answer這表明,在Linux上可以讀取本地地址傳入UDP數據包,並將其設置傳出的數據包。在C中是可能的;雖然我不確定Python。

+0

這聽起來像這裏發生的事情。我寫了一個C客戶端,它和上面的Python做了同樣的事情,而且我仍然得到相同的結果,所以「拒絕來自其他IP的響應」必須在C庫級別發生(這實際上意味着我堅持了它)。 看起來我還需要綁定到特定的地址。謝謝您的幫助! – 2009-08-21 02:19:40

1

這只是UDP的規則?

這是與 Python的UDPServer類問題/限制嗎?

令人懷疑。

這是我做錯了什麼嗎?

你的程序看起來正確。

數據報沒有到達服務器的原因有很多。 UDP是無連接的,因此您的客戶端只需將ping發送到以太網,而不知道是否有人接收到它。

看看你是否被允許綁定到該地址。有一個名爲netcat的很棒的小程序,適用於低級網絡訪問。它並不總是在每個系統上都可用,但它很容易下載和編譯。

nc -l -s 188.40.77.236 -p 24440 -u 

如果你運行客戶端程序,就像之前,你應該看到「平安」字樣的終端上。 (你可以輸入Pong並將其設置回客戶端,這很有趣。)如果你使用ping命令,網絡問題不是問題,並且Python服務器程序或庫有問題。如果您沒有ping通,則無法建立連接。 「請聯繫您的網絡管理員尋求幫助。」

檢查事項將包括...

  1. 防火牆的問題?
  2. 別名網絡接口的配置問題。
  3. 用戶權限問題。
+0

問題沒有綁定到地址,因爲服務器獲得'ping' - 但客戶端沒有得到'pong'。 運行netcat綁定到該IP工作(但也是套接字服務器)。運行netcat綁定到0.0.0.0 **不**工作。 – 2009-08-21 01:27:53

+0

我編輯了這個問題,使問題更清楚,問題與響應有關,而不是服務器接收到客戶端數據包。 – 2009-08-21 02:23:34