python socket.recv 挂起,但是我在 tcpdump 中看到了框架

python socket.recv hangs, however I see the frame in tcpdump

我有下面的代码来发送命令,但是 python 脚本永远不会退出。它挂起。 我正在使用 RHEL 6.4 x86_64。 scapy srp1 也挂了。

from socket import *
from scapy.all import *
from myproto import *

def sendeth(REQUEST, interface = "eth0"):
    """Send raw Ethernet packet on interface."""
    s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
    s.bind((interface, 0))
    s.send(REQUEST)
    data = s.recv(2048)
    hexdump(data)


p = Ether()/MYPROTO()/MYPROTO1()
hexdump(p)

if __name__ == "__main__":
    print "Sent %d-byte Ethernet packet on eth3" % sendeth(str(p), 'eth3')

但是执行后,我在tcpdump上看到了帧,但是python代码永远不会退出,需要一个控件^C。

tcpdump: WARNING: eth3: no IPv4 address assigned
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth3, link-type EN10MB (Ethernet), capture size 65535 bytes
17:10:37.122445 00:00:00:00:00:00 (oui Ethernet) > Broadcast, ethertype  Unknown (0x8096), length 34:
    0x0000:  ffff ffff ffff 0000 0000 0000 8096 0001
    0x0010:  0001 1500 0000 0000 0000 0000 0000 ffff
    0x0020:  eafe
17:10:37.133248 00:04:25:1c:a0:02 (oui Unknown) > Broadcast, ethertype Unknown (0x8096), length 76:
    0x0000:  ffff ffff ffff 0004 251c a002 8096 0001
    0x0010:  0001 9500 0028 0000 0000 0000 0000 0000
    0x0020:  0000 f1f0 f100 0000 0000 0000 0000 0000
    0x0030:  0000 0000 0000 0803 0087 1634 8096 8096
    0x0040:  e4f2 0000 0f21 fffc 5427 ffff

当您在套接字上调用 recv() 时,内核中的网络堆栈已经分派了您正在发送的帧,并且注意到本地主机上没有任何东西在等待它, 丢弃了它。

尝试 运行 发送方和接收方作为不同的进程。

编辑 0:

尝试将您的特定协议编号作为第三个参数添加到 socket()。这是一个从我的 eth0 在 Debian 上抓取十个以太网帧的示例(需要 root 权限):

import socket
# from linux/if_etheer.h, all ethernet protocols, be very careful
ETH_P_ALL=0x0003
s=socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(ETH_P_ALL))
s.bind(('eth0', 0)) 
for n in range(10):
    print n, len(s.recv(2048))

strace 在等待 select 时帮助找到了解决方案 - 解决方案是 -

from socket import *
from scapy.all import *
from myproto import *
MYPROTOTYPE = 0x8096

p = Ether()/MYPROTO()/MYPROTO1()
hexdump(p)

from socket import socket, PF_PACKET, SOCK_RAW

s = socket(PF_PACKET, SOCK_RAW, MYPROTOTYPE)
s.bind(("eth3", MYPROTOTYPE))
s.send(str(p))
data = s.recv(2048)
hexdump(data)