如何在Python中将套接字绑定到接口(缺少socket.SO_BINDTODEVICE)

8

这可能是一件非常简单的事情。 我是 Python 的新手,所以请不要对我进行严厉批评。

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, IN.SO_BINDTODEVICE, "eth1"+'\0')

上述命令输出如下:
NameError: name 'IN' is not defined

the only import I have is

import socket
4个回答

12
如果您不理解错误消息,那么它意味着您正在引用一个名称IN,但此时该名称不可用。您的代码片段可能缺少一个import语句。
出于可移植性的考虑,套接字模块可能不提供SO_BINDTODEVICE选项。如果您绝对确信您正在运行支持它的Linux系统,则尝试将其替换为其数字值,即25
s.setsockopt(socket.SOL_SOCKET, 25, "eth1"+'\0')

或者针对Python 3:

s.setsockopt(socket.SOL_SOCKET, 25, str("eth1" + '\0').encode('utf-8'))

1
我习惯使用C语言,但想尝试用Python编写。将我的导入语句更改为“import socket, IN”即可解决问题。 - user916499
如果您没有直接使用套接字模块,可以使用猴子补丁技术,具体请参考https://dev59.com/mWcs5IYBdhLWcg3wym0h。 - Daniel F
IN模块是Linux平台上的标准模块。它包含了大部分来自/usr/include/netinet/in.h的常量。毫无疑问,在该文件中,SO_BINDTODEVICE被设置为25。 - init_js
'\0' 是必要的,因为数据很可能直接传递给 C API。如果名称来自用户输入,我还会将接口名称截断为 IF_NAMESIZE(包括空字节的 16 个字符):... , 25, ifname[:16]+'\0') - init_js

3
在Python中,SO_BINDTODEVICE 存在于IN 模块中。导入IN将解决此问题。
import socket
import IN

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, IN.SO_BINDTODEVICE, "eth0")

2

您甚至可以“导出”一个缺失的选项:

if not hasattr(socket,'SO_BINDTODEVICE') :
    socket.SO_BINDTODEVICE = 25

那么

sock.setsockopt(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, interface+'\0')

0

注意:SO_BINDTODEVICE在数据包套接字中无法使用- Linux man-page man 7 socket

它不支持数据包套接字(请在此处使用普通的bind(2))。

以太网1(eth1)的Python示例与bind():

rawSocket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(3))
rawSocket.bind(('eth1',0))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接