陈某某的网络日志

活到老学到老,学习无止境

0%

udp取得IP地址

问题需求和分析

最近遇到个小需求:有一台嵌入式设备带网卡(moxa NE-4110S),和PC用网线直连,现想要知道设备的IP地址,其实moxa官方提供了相关的应用程序扫描IP地址。但我在想有没有简单的方法,直接取得设备IP,不需要在图形界面上操作。环境中PC端网卡一般为静态地址,但和设备端很可能在不同网段,简单的循环ping和arp -a肯定不行了。想不如就用python 写一个小程序 当练手了。一开始不知道怎么下手,先看看moxa的程序是怎么做的,它扫描的时候用wireshark抓个包,原来是udp广播,顺手也补习了udp和socket的一点知识。

wireshark抓包图

从图中可以看出,第一次udp广播的数据是固定的,设备端收到后都会回复,回复ip就已经知道了。我猜moxa网卡固件上电就开了udp服务端口,那我就模仿它的应用程序端给它发udp包就行了。首先要得到本机的地址,我调用的windows命令加一点正则表达式,再就是socket 发udp广播,取回数据。由于是设备直连,发一个udp包就够用了。暂没多考虑其它异常情况。

python代码

下面是主要代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import os
import re
from socket import *
HOST = '<broadcast>' #'255.255.255.255'
PORT = 4800 #服务端的监听端口
ADDR = (HOST,PORT)
LOCALPORT = 13316 #本机端口
BUFSIZE = 1024
DATA = b"\x01\x00\x00\x08\x00\x00\x00\x00" #要发送的字节流数据,原设备程序search时由wireshark抓取

pattern = r"描述.*(controller|控制器).*" #为了正确找到网卡,这个正则可能要调整
rx = re.compile(pattern,re.IGNORECASE)

def getLocalIP():
allinfo = os.popen("ipconfig -all").readlines()
for line in allinfo:
#匹配到行 返回行号
if rx.search(line):
n = allinfo.index(line)
break
netinfo = allinfo[n:n+6] #切分包含ip的子序列
for line in netinfo:
if "IPv4" in line:
ip = line.split(':')[1].split('(')[0].strip() #用split()拆分,strip()去空格。
return ip
else:
print("未插网线或未打开设备!")

def getDeviceIP():
udpsocket = socket(AF_INET,SOCK_DGRAM)
udpsocket.bind((getLocalIP(),LOCALPORT)) #绑到本机端口
udpsocket.setsockopt(SOL_SOCKET,SO_BROADCAST,1) #SO_BROADCAST 开启广播
udpsocket.sendto(DATA,ADDR) # 发送数据
recvdata,addr = udpsocket.recvfrom(BUFSIZE)
udpsocket.close()
deviceIP = addr[0]
return deviceIP

if __name__ == '__main__':
print(getDeviceIP())