这是一个改编自UDP 发现的 ZeroMQ UDP ping 函数,Python 中的模型 1通过禁用广播,仅 ping 一个 IP 地址,在第一次回复后返回,添加一个计数器以限制 ping 尝试的次数,并在消息接收期间添加额外的错误处理. 后者是因为我的网络中的一个主机强行关闭了导致 socket.error: [Errno 10054] 的连接。它已经过测试,发现可以与 Python 2.7.10 和 3.4.3 一起使用。
from __future__ import print_function
import os
import socket
import sys
import time
import zmq
def udpping(ip):
PING_PORT_NUMBER = 9999
PING_MSG_SIZE = 1
PING_INTERVAL = 1 # once per second, sets minimum initial timeout
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
# uncomment the line below for broadcast to 255.255.255.255
# sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.bind(('', PING_PORT_NUMBER))
poller = zmq.Poller()
poller.register(sock, zmq.POLLIN)
ping_at = time.time()
limit = 5 # only limit ping attempts will be made
count = 0
while True:
count += 1
timeout = ping_at - time.time()
if timeout < 0:
timeout = 0
try:
events = dict(poller.poll(1000* timeout))
except KeyboardInterrupt:
return (1,None,None)
try:
if sock.fileno() in events:
msg, addrinfo = sock.recvfrom(PING_MSG_SIZE)
return (2,"found %s:%d" % addrinfo,None)
except socket.error as e:
return (3,'error during msg receive:',e)
if time.time() >= ping_at:
# the line below is for broadcasting
# sock.sendto(b'!', 0, ("255.255.255.255", PING_PORT_NUMBER))
sock.sendto(b'!', 0, (ip, PING_PORT_NUMBER))
ping_at = time.time() + PING_INTERVAL
if count == limit:
return (4,limit,None)
ip = '192.168.159.21'
c,m,e = udpping(ip)
下面显示了输出处理。对于二元决策,仅当 c == 2 时 ping 成功。
if c == 1:
print('ping attempt stopped by KeyboardInterrupt')
elif c == 2:
print(m)
elif c == 3:
print(m,e)
elif c == 4:
print('no response from',ip,'after',m,'attempts')
# prints 'found 192.168.159.21:9999' immediately in my net