python icmp原始套接字实现
我对 python 比较陌生,所以请体谅...
我正在通过 raw_sockets 实现服务器和客户端。 我有必要的特权。
现在,我定义的服务器:
host = socket.gethostbyname(socket.gethostname())
address = (host, 22224)
sockSer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
sockSer.bind(address)
sockSer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
packet, addr = sockSer .recvfrom(4096) # wait for packet from client
Q1)为什么我不能简单地键入:hosts = 'localhost'。 如果我这样做,它不允许我编写以下行:sockSer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)。然后服务器收不到我客户端的消息。 仅当执行 gethostbyname(socket.gethostname()) 时我得到 192.168.1.101 然后就可以了。
在不同的班级: 客户端套接字:
host = socket.gethostbyname(socket.gethostname())
address = (host, 22224)
sockCli = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
Q2)我还需要输入:sockCli.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) 或者也许是 sockCli.connect(地址)?似乎无需连接命令即可工作。 对于客户端套接字?
现在,当我执行以下操作时会出现问题: 1)从客户端发送数据包到服务器:
header=...
payload='a'
sockCli.sendto(header + payload, address)
2)在服务器中接收数据包并将某些内容发送回客户端:
while(true):
data, addr = sockSer.recvfrom(4096)
header2=...
payload2='b'
sockSer.sendto(header2 + payload2, addr)
现在,我的重要问题是: Q3) 服务器只向客户端发送了 1 个数据包,负载为“b”。 发生的情况是,我的客户端实际上在 while 循环中收到了 2 个数据包: 第一个数据包是客户端本身发送到服务器的数据包,另一个数据包是客户端从服务器获取的数据包。 因此我的输出是“ab”而不是简单的“b” 为什么会这样???
注意:我没有输入完整的代码,但我认为我的语法、解析、标头组成等都是正确的。 我的代码中有明显的问题吗? 如果需要的话我会上传整个代码。
谢谢
i am relatively new to python, so please be considerate...
i'm implementing a server and a client via raw_sockets.
i have the necessary privileges.
now, the server i defined so:
host = socket.gethostbyname(socket.gethostname())
address = (host, 22224)
sockSer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
sockSer.bind(address)
sockSer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
packet, addr = sockSer .recvfrom(4096) # wait for packet from client
Q1) why can't i simply type: hosts = 'localhost'.
if i do so, it doesn't allow me to write the line: sockSer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON). and then the server doesn't receive my client's messages.
only when doing gethostbyname(socket.gethostname()) i get 192.168.1.101
and then it works.
in a different class:
the client socket:
host = socket.gethostbyname(socket.gethostname())
address = (host, 22224)
sockCli = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
Q2) do i also need to type: sockCli.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
or maybe sockCli.connect(address)? seems that it works without the connect command.
for the client socket?
now, the problems arise when i do the following:
1) send a packet from client to server:
header=...
payload='a'
sockCli.sendto(header + payload, address)
2) receive packet in server and send something back to client:
while(true):
data, addr = sockSer.recvfrom(4096)
header2=...
payload2='b'
sockSer.sendto(header2 + payload2, addr)
now, my important question is:
Q3) the server sent only 1 packet to client, with payload 'b'.
what happens is, my client actually receives 2 packets in the while loop:
first packet is what the client itself sent to server, and the other packet is what the client got from the server.
hence my output is 'ab' instead of simply 'b'
why is this happening???
NOTE: i didn't type the entire code, but i think my syntax,parsing,header composition etc.. are correct.
is there an obvious problem in my code?
if necessary i'll upload the entire code.
thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我也得到了这个。
我的解决方案是在接收代码中添加一个判断,比如我发送Ping包所以我只想要ECHO回复(类型0代码0),我写
,你也可以写为
如果地址== my_ip:
继续
似乎没有什么顺利的解决办法
I got this too.
my solution is add a judge in the receive code,such as if I send Ping package so I only want ECHO Reply( type 0 code 0), I write
and you also can write as
if addr == my_ip:
continue
It seems not has any smooth solution
Q1:我能够绑定到 localhost 并使用两个参数调用 IOCTL。假设您的客户端也在同一系统上运行,请确保客户端发送到“localhost”,否则您的服务器将永远不会收到数据包。如果您的客户端位于另一个系统上,显然您的服务器将永远不会收到数据包。
Q2:发送数据包不需要 IOCTL。只需通过 sendto() 发送即可。
Q3:您看到两个回复的原因是,除了您自己的用户空间代码之外,内核还正在处理 echo 请求。
尽管您可以使用 ICMP 进行任意消息传递,但正如其他人指出的那样,这不是其预期设计。您可能会发现您的数据部分在消息回复中被截断。例如,当发送回显请求时,您的回复可能会包含您发送的所有内容;但是,类型 3 代码 3 的回复可能不包含您的数据,而仅包含 ICMP 标头的前 8 个字节。
Q1: I was able to bind to localhost and call IOCTL with both parameters just fine. Assuming your client is also running on the same system, ensure the client is sending to "localhost", otherwise your server will never receive the packets. If your client is on another system, obviously your server will never receive the packets.
Q2: You do not need IOCTL for sending the packet. Just send it via sendto().
Q3: The reason you're seeing two replies is, the kernel is also processing the echo request, in addition to your own user-space code.
Although you can use ICMP for arbitrary message passing, as someone else pointed out this isn't its intended design. You may find that your data portion is truncated out in message replies. For example, when sending echo requests, your reply likely will contain everything you sent; however, a reply that is type 3 code 3 may not include your data, but only the first 8 bytes of the ICMP header.