Socket不会绑定:没有这样的设备

时间:2014-12-30 22:25:48

标签: python sockets

所以我有这段Python 3代码:

import socket
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
s.bind(('eth0', 0))
s.send(eth_packet)

此代码适用于我的Raspberry Pi,但不适用于我的外部服务器。当我尝试在我的外部服务器上运行它时,我得到:

# sudo python3 test.py
s.send(eth_packet)
socket.error: [Errno 19] No such device

我检查了网络接口输出(通过python脚本): 外部服务器(debian):

['lo [index=1, IPv4=127.0.0.1, IPv6=::1]', 'eth0:0 [index=2, IPv4=xxxxx, IPv6=None]', 'eth0 [index=2, IPv4=yyyyyy, IPv6=zzzzzzz]']

Raspberry pi:

['lo [index=1, IPv4=127.0.0.1, IPv6=None]', 'eth0 [index=2, IPv4=rrrrr, IPv6=None]']

有人可以解释发生了什么吗?我只是想发送一个手工制作的消息,但这个错误一直困扰着我,这可能是我服务器驱动程序的问题吗?这与ifconfig相同。

修改

好的,我在这个例子中使用了strace:

#!/usr/bin/env python3

import socket
import binascii
import struct

test= '000a959d6816'
packet= struct.pack("!6s", binascii.unhexlify(bytes(test, 'UTF-8')))
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
s.bind(('eth0', 0))
s.send(packet)

这是关于strace的重要部分:

socket(PF_PACKET, SOCK_RAW, 0)          = 3
ioctl(3, SIOCGIFINDEX, {ifr_name="eth0", ifr_index=2}) = 0
bind(3, {sa_family=AF_PACKET, proto=0000, if2, pkttype=PACKET_HOST, addr(0)={0, }, 20) = 0
sendto(3, "\0\n\225\235h\26", 6, 0, NULL, 0) = -1 ENXIO (No such device or address)
open("test.py", O_RDONLY)               = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=247, ...}) = 0
ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fff86c5f090) = -1 ENOTTY (Inappropriate ioctl for device)
fstat(4, {st_mode=S_IFREG|0644, st_size=247, ...}) = 0
lseek(4, 0, SEEK_CUR)                   = 0
dup(4)                                  = 5
fcntl(5, F_GETFL)                       = 0x8000 (flags O_RDONLY|O_LARGEFILE)
fstat(5, {st_mode=S_IFREG|0644, st_size=247, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc1251c2000
lseek(5, 0, SEEK_CUR)                   = 0
read(5, "#!/usr/bin/env python3\n\nimport s"..., 4096) = 247
close(5)                                = 0
munmap(0x7fc1251c2000, 4096)            = 0
lseek(4, 0, SEEK_SET)                   = 0
lseek(4, 0, SEEK_CUR)                   = 0
read(4, "#!/usr/bin/env python3\n\nimport s"..., 4096) = 247
close(4)                                = 0
write(2, "Traceback (most recent call last"..., 143Traceback (most recent call last):
  File "test.py", line 11, in <module>
    s.send(packet)
socket.error: [Errno 6] No such device or address
) = 143
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7fc1264050a0}, {0x428787, [], SA_RESTORER, 0x7fc1264050a0}, 8) = 0
close(3)                                = 0

3 个答案:

答案 0 :(得分:5)

在接口上绑定带有系列PACKET的RAW套接字时,需要一个包含2个对象的元组:

(interfaceName, protoNumber)

或5个对象:

(interfaceName, protoNumber, pkttype, hatype, haddr)

您在protoNumber中指定0,但系统中可能不存在protoNumber 0。

Documentation about packet family: packet(7)

  

sll_protocol 是网络字节中的标准以太网协议类型   订单文件中定义的订单。

尝试在 linux / if_ether.h 中找到正确的协议编号。

答案 1 :(得分:1)

假设您的外部服务器在Linux下运行,有一些原因无法运行您的程序。

正如Figus已经指出的那样,你实际上使用的协议号0可能没有定义。你可能会更幸运:

s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, proto)

其中proto是与linux / if_ether.h中的ETH_P_ALL对应的协议号(在某些Linux机器上为3)

man packet也说:只有具有有效UID 0或CAP_NET_RAW功能的进程才能打开数据包套接字。因此,这意味着您必须在外部服务器上拥有root权限才能运行代码。

答案 2 :(得分:-3)

这是一个可以发送手工消息的客户端。变量ip和port是服务器的端口和IP地址,下面程序中的值是示例

import socket
ip = "127.0.0.1"
port = 447
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, port))
msg = ("hello ex. message")
s.send(msg.encode('ascii'))
rep = s.recv(1024)
rep1 = (rep.decode('ascii'))
print rep1

,服务器是

import socket
ip = "127.0.0.1"
port = 447
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((ip, port))
s.listen(15)
con, addr = s.accept()
msg = con.recv(1024)
msg1 = (msg.decode('ascii'))
print (msg1)
rep = ("got message")
con.send(rep.encode('ascii'))

我希望这个答案有所帮助,这就是你要找的。