我正在使用此代码通过Wlan网络使用我的设备无线IP地址组播消息:
import socket
MCAST_GRP = '224.1.1.1'
MCAST_PORT = 5007
IP=''
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 1))
IP = s.getsockname()[0]
print(IP)
s.close()
except:
print("Could not get IP")
s.close()
try:
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
udp_socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
udp_socket.sendto(IP, (MCAST_GRP, MCAST_PORT))
udp_socket.close()
print("Multicast Message sent.")
except:
print("Message not sent")
udp_socket.close()
所有设备都通过无线路由器连接,路由器允许组播消息。代码是获取设备的IP并以多播消息发送它。这些设备混合使用Linux Debian 8和Windows 10操作系统。
在设备中,唯一有效的网络接口是无线的,这可以立即使用。问题是有时候有多个活动网络接口可用,我需要选择无线网络接口(如果有)。我试图减少无线接口的度量参数的值并且它有效,但我必须手动执行此操作,我需要它自动化。
我想知道如何补充我的代码,以便能够选择所需的网络接口(希望以可移植的方式),组播消息并接收它们。提前谢谢。
答案 0 :(得分:1)
在连接之前从所需接口绑定到IP似乎对大多数人起作用。诀窍是获得IP。 详情请见 Can Python select what network adapter when opening a socket?
答案 1 :(得分:0)
您可以尝试使用以下脚本检索IPv4 / IPv6网络接口的信息。希望这会有所帮助。
# -*- coding: utf-8 -*-
from ctypes import *
from sys import platform
from socket import AF_INET, AF_INET6, inet_ntop
try:
from socket import AF_PACKET
except ImportError:
AF_PACKET = -1
if platform.startswith("darwin") or platform.startswith("freebsd"):
AF_LINK = 18
IFT_ETHER = 0x6
else:
AF_LINK = -1
IFT_ETHER = -1
def get_if_addresses():
"""
Retrieve all relevant information of IPv4/IPv6 network interfaces.
Based on http://pastebin.com/wxjai3Mw (Author unknown)
"""
# getifaddr structs
class ifa_ifu_u(Union):
_fields_ = [
("ifu_broadaddr", c_void_p),
("ifu_dstaddr", c_void_p)
]
class ifaddrs(Structure):
_fields_ = [
("ifa_next", c_void_p),
("ifa_name", c_char_p),
("ifa_flags", c_uint),
("ifa_addr", c_void_p),
("ifa_netmask", c_void_p),
("ifa_ifu", ifa_ifu_u),
("ifa_data", c_void_p)
]
# AF_UNKNOWN / generic
if platform.startswith("darwin") or platform.startswith("freebsd"):
class sockaddr(Structure):
_fields_ = [
("sa_len", c_uint8),
("sa_family", c_uint8),
("sa_data", (c_uint8 * 14))
]
else:
class sockaddr(Structure):
_fields_ = [
("sa_family", c_uint16),
("sa_data", (c_uint8 * 14))
]
# AF_INET / IPv4
class in_addr(Union):
_fields_ = [
("s_addr", c_uint32),
]
if platform.startswith("darwin") or platform.startswith("freebsd"):
class sockaddr_in(Structure):
_fields_ = [
("sin_len", c_uint8),
("sin_family", c_uint8),
("sin_port", c_ushort),
("sin_addr", in_addr),
("sin_zero", (c_char * 8)) # padding
]
else:
class sockaddr_in(Structure):
_fields_ = [
("sin_family", c_short),
("sin_port", c_ushort),
("sin_addr", in_addr),
("sin_zero", (c_char * 8)) # padding
]
# AF_INET6 / IPv6
class in6_u(Union):
_fields_ = [
("u6_addr8", (c_uint8 * 16)),
("u6_addr16", (c_uint16 * 8)),
("u6_addr32", (c_uint32 * 4))
]
class in6_addr(Union):
_fields_ = [
("in6_u", in6_u),
]
if platform.startswith("darwin") or platform.startswith("freebsd"):
class sockaddr_in6(Structure):
_fields_ = [
("sin6_len", c_uint8),
("sin6_family", c_uint8),
("sin6_port", c_ushort),
("sin6_flowinfo", c_uint32),
("sin6_addr", in6_addr),
("sin6_scope_id", c_uint32),
]
else:
class sockaddr_in6(Structure):
_fields_ = [
("sin6_family", c_short),
("sin6_port", c_ushort),
("sin6_flowinfo", c_uint32),
("sin6_addr", in6_addr),
("sin6_scope_id", c_uint32),
]
# AF_PACKET / Linux
class sockaddr_ll(Structure):
_fields_ = [
("sll_family", c_uint16),
("sll_protocol", c_uint16),
("sll_ifindex", c_uint32),
("sll_hatype", c_uint16),
("sll_pktype", c_uint8),
("sll_halen", c_uint8),
("sll_addr", (c_uint8 * 8))
]
# AF_LINK / BSD|OSX
class sockaddr_dl(Structure):
_fields_ = [
("sdl_len", c_uint8),
("sdl_family", c_uint8),
("sdl_index", c_uint16),
("sdl_type", c_uint8),
("sdl_nlen", c_uint8),
("sdl_alen", c_uint8),
("sdl_slen", c_uint8),
("sdl_data", (c_uint8 * 46))
]
if platform.startswith("darwin"):
libc = CDLL("libSystem.dylib")
elif platform.startswith("freebsd"):
libc = CDLL("libc.so")
else:
libc = CDLL("libc.so.6")
ptr = c_void_p(None)
result = libc.getifaddrs(pointer(ptr))
if result:
return None
ifa = ifaddrs.from_address(ptr.value)
result = []
while ifa:
# Python 2 gives us a string, Python 3 an array of bytes
if type(ifa.ifa_name) is str:
name = ifa.ifa_name
else:
name = ifa.ifa_name.decode()
if ifa.ifa_addr:
sa = sockaddr.from_address(ifa.ifa_addr)
data = {}
if sa.sa_family == AF_INET:
if ifa.ifa_addr is not None:
si = sockaddr_in.from_address(ifa.ifa_addr)
data['addr'] = inet_ntop(AF_INET, si.sin_addr)
if ifa.ifa_netmask is not None:
si = sockaddr_in.from_address(ifa.ifa_netmask)
data['netmask'] = inet_ntop(AF_INET, si.sin_addr)
# check if a valid broadcast address is set and retrieve it
# 0x2 == IFF_BROADCAST
if ifa.ifa_flags & 0x2:
si = sockaddr_in.from_address(ifa.ifa_ifu.ifu_broadaddr)
data['broadcast'] = inet_ntop(AF_INET, si.sin_addr)
if sa.sa_family == AF_INET6:
if ifa.ifa_addr is not None:
si = sockaddr_in6.from_address(ifa.ifa_addr)
data['addr'] = inet_ntop(AF_INET6, si.sin6_addr)
if data['addr'].startswith('fe80:'):
data['scope'] = si.sin6_scope_id
if ifa.ifa_netmask is not None:
si = sockaddr_in6.from_address(ifa.ifa_netmask)
data['netmask'] = inet_ntop(AF_INET6, si.sin6_addr)
if sa.sa_family == AF_PACKET:
if ifa.ifa_addr is not None:
si = sockaddr_ll.from_address(ifa.ifa_addr)
addr = ""
total = 0
for i in range(si.sll_halen):
total += si.sll_addr[i]
addr += "%02x:" % si.sll_addr[i]
addr = addr[:-1]
if total > 0:
data['addr'] = addr
if sa.sa_family == AF_LINK:
dl = sockaddr_dl.from_address(ifa.ifa_addr)
if dl.sdl_type == IFT_ETHER:
addr = ""
for i in range(dl.sdl_alen):
addr += "%02x:" % dl.sdl_data[dl.sdl_nlen + i]
addr = addr[:-1]
data['addr'] = addr
if len(data) > 0:
iface = {}
for interface in result:
if name in interface.keys():
iface = interface
break
if iface:
iface[name][sa.sa_family] = data
else:
iface[name] = { sa.sa_family : data }
result.append(iface)
if ifa.ifa_next:
ifa = ifaddrs.from_address(ifa.ifa_next)
else:
break
libc.freeifaddrs(ptr)
return result
答案 2 :(得分:0)
经过测试,可以在Linux Debian 8和Windows 10中使用Python 2.7。
对于Linux:
def get_local_wireless_ip_linux():
import fcntl
import struct
import socket
ifname = 'wlan0'
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
wlan0_ip = (socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x8915, struct.pack('256s', ifname[:15]))[20:24]))
return wlan0_ip
,对于Windows:
def get_local_wireless_ip_windows():
import subprocess
arp = subprocess.check_output('arp -a')
local_ipv4 = []
for line in arp.split('\n'):
if 'Interface' in line:
local_ipv4.append(line.split(':')[1].split('---')[0].strip())
return local_ipv4[-1]