所以我正在使用UDP进行分配的基本“ping”应用程序,除了socket.settimeout()的实现之外,一切正常。 我似乎无法弄清楚为什么,但它与绑定套接字有关。它可能只是Python中的一个怪癖,但我想在记录它之前确认它。 我不是在寻找一个功能性的代码答案(那是作弊),而是为什么我的东西被打破了。 (例如:Python不喜欢同一台机器上的客户端/服务器的一些未记录的原因等)
Python套接字超时详细信息:http://docs.python.org/2/library/socket.html#socket.socket.settimeout
在下面的代码中,与在同一台机器上运行的服务器的通信成功,但仅在客户端未绑定到套接字时。但如果它没有绑定到套接字,则超时系统会失败(通过关闭服务器进行测试,其中所有十个超时都会立即打印出来)。
注意:代码并不理想,但这是一个网络理论类而不是编程类。它必须最终工作。我现在可以把它交给A,但是我想知道为什么超时功能不起作用。
编辑:为了澄清一个问题,在我意识到UDP不需要它之后,在看到服务器代码之后,在客户端使用Bind,但它碰巧使得超时功能工作正常,但打破了正常的操作。 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)
答案 0 :(得分: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
如果这是一个Networking类项目并且您正在尝试实现客户端 - 服务器体系结构,那么您永远不应该在客户端代码中调用 bind ,因为客户端永远不应该充当服务器并且客户端应该连接到侦听服务器而不是服务器连接到客户端。
更新:
可能需要从TCP客户端 - 服务器设计调用绑定,而不是从UDP客户端 - 服务器模型调用绑定,因为UDP是发送和遗忘设计,并且没有低级别数据包发送成功确认。 UDP数据包本身就有源地址和端口。
答案 1 :(得分:0)
我通过删除异常处理找到了问题的原因。服务器关闭时出现套接字错误,特别是“socket.error:[Errno 10054]当尝试从套接字读取时,远程主机强行关闭现有连接”。 当套接字没有绑定在Python中时,这显然忽略了超时功能(这就是为什么当我绑定它时超时工作)。 如果我运行服务器,但只是让它不发送任何数据(通过注释最后一行),程序在没有收到数据包时会正确超时。 我还将使用更具体的异常处理程序 最后,它只是Python中的一个怪癖,而且UDP是无连接的事实。
另外,有人提到使用“选择”来解决这个问题。我调查了一下,我最终得到了一个if ... else语句块,它有点有效,但原生例外是首选。 谢谢大家。
-Jimmy