1

所以我正在制作一个使用 UDP 进行分配的基本“ping”应用程序,除了 socket.settimeout() 的实现之外,一切都在工作。我似乎无法弄清楚为什么,但这与绑定的套接字有关。这可能只是 Python 中的一个怪癖,但我想在记录之前确认它。我不是在寻找功能代码答案(那是作弊),而是为什么我所拥有的东西被破坏了。(例如:Python不喜欢同一台机器上的客户端/服务器等一些未记录的原因)

Python 套接字超时详细信息: http: //docs.python.org/2/library/socket.html#socket.socket.settimeout

在下面的代码中,与运行在同一台机器上的服务器的通信是成功的,但前提是客户端没有绑定到套接字。但是如果它没有绑定到套接字,超时系统就会失败(这是通过关闭服务器来测试的,其中所有十个超时都会立即打印出来)。

注意:代码并不理想,但这是网络理论课而不是编程课。它只需要最终起作用。我现在可以交出并获得 A,但我想了解为什么超时功能不起作用。

编辑:为了澄清一个问题,在客户端使用 Bind 是在我意识到 UDP 不需要它之前看到服务器代码之后使用它,但它恰好使超时功能正常工作,但破坏了正常操作。socket.settimeout() 声明可能只适用于 TCP 吗?

客户端代码(有超时):

import socket
import time
import select


data = "Re-verify our range to target... one ping only. \n"

addrDest = ("127.0.0.1",8675)
addrLocal = ("127.0.0.1",12345)

totalTime = 0
averageTime = 0
totalPings = 0
#timeout_seconds = 1.0

UDPSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
UDPSock.bind(addrLocal) 
# adding bind here even though it's UDP makes timeout work,
# but breaks normal functionality
UDPSock.settimeout(1)


while (totalPings < 10):
 totalPings = (totalPings + 1)
 start = time.clock()
 str_list = []
 str_list.append(str(totalPings))
 str_list.append(" ")
 str_list.append(str(start))
 str_list.append(" ")
 str_list.append(data)
 dataOut = ''.join(str_list)
 UDPSock.sendto(dataOut,addrDest)
 try:
      dataIn,addrIn = UDPSock.recvfrom(1024)
      print dataIn.strip(),"\n",addrIn
      elapsed = ((time.clock() - start) * 1000)
      print elapsed, " ms round trip"
 except socket.error:
      print "Connection timed out for Packet #", totalPings

服务器代码:

import socket

UDPSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

# (to all IP addresses on this system)
listen_addr = ("",8675)
UDPSock.bind(listen_addr)

# Report on all data packets received and
# where they came from in each case (as this is
# UDP, each may be from a different source and it's
# up to the server to sort this out!)
while True:
    data,addr = UDPSock.recvfrom(1024)
    print data.strip(),addr
    UDPSock.sendto(data,addr)
4

2 回答 2

2

为什么需要绑定到客户端的本地地址?客户端在任何时候也会充当服务器吗?如果没有,则根本不需要绑定客户端。仅当您需要客户端充当服务器时才需要特定端口,如果您不调用 bind 它将创建一个随机端口,范围为(保留 0 - 1023)1024 - 65535(如果我没记错的话)和这将是 UDP 数据包中的源端口,源地址是客户端运行的地址。

根据伯克利套接字

bind() assigns a socket to an address. When a socket is created using socket(), 
it is only given a protocol family, but not assigned an address. This association with an address must be performed with the bind() system call before the socket can accept connections to other hosts

如果这是一个网络类项目,并且您正在尝试实现客户端-服务器体系结构,那么您不应该从客户端代码中调用bind,因为客户端不应该充当服务器,客户端应该连接到侦听服务器,而不是连接到客户端的服务器。

更新:

可能需要从 TCP 客户端-服务器设计而不是 UDP 客户端-服务器模型调用绑定,因为 UDP 是一种发送后忘记的设计,并且没有低级别的数据包发送成功确认。UDP 数据包本身将具有源地址和端口。

于 2013-02-20T06:57:04.767 回答
0

我通过删除异常处理找到了问题的原因。关闭服务器时出现套接字错误,特别是“socket.error:[Errno 10054] 现有连接被远程主机强制关闭”当它尝试从套接字读取时。当套接字未在 Python 中绑定时,这显然忽略了超时函数(这就是我绑定它时超时起作用的原因)。如果我运行服务器,但只是让它不发送任何数据(通过注释最后一行),程序在没有收到返回的数据包时正确超时。我还将使用更具体的异常处理程序最后,这只是 Python 中的一个怪癖,而 UDP 是无连接的事实。

另外,有人提到使用“选择”来解决这个问题。我调查了一下,我最终会得到一个 if...else 语句块,它有点工作,但首选本机异常。谢谢大家。

-吉米

于 2013-02-20T19:53:37.903 回答