我有正在发送消息到服务器这个简单的客户端代码,然后相呼应的服务器响应。
import socket, sys, time
HOST = 'localhost'
PORT = 11000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
msg = raw_input()
s.send(msg)
data = s.recv(len(msg))
s.close()
print 'Received: ', data
我想,为了能够得到IP_ID场出服务器的响应报文在这里使用原始套接字,但我不知道怎么样。
不管我多么在互联网上读到它,我没有找到如何做到这一点的好例子。
(只是为了澄清,我并不真的需要一个原始数据包发送到服务器,我可以使用正常的SOCK_STREAM发送的消息,但我需要使用原始套接字获得响应” IP_ID。)
任何人都可以编辑我的代码,并告诉我,在simpliest方式,怎么办呢? 所有我设法找到了,是我需要socket.SOCK_RAW更换socket.SOCK_STREAM了,但是我还相距甚远。
非常感谢
从原始套接字读和解析出IP_ID很简单:
response, addr = s.recvfrom(65535)
response_id = struct.unpack('!H', response[4:6])
print response_id
难的是让别人给你摆在首位的包。 我敢肯定,你不能在同一时间使用原始模式和流模式相同的插座,所以你将需要更换connect
,并send
了一堆复杂得多的代码,构造并发送适当的TCP数据包发起的连接。 还有像图书馆scapy
,将尽一切坚硬的东西给你,但是如果你想要做手工,你只需要阅读RFC 791和RFC 793认真,做的所有繁琐的东西(确保你得到所有字节序权),你对你的方式。
在* BSD(包括OS X),内核将填写IP长度,TCP长度,而且,最重要的是,TCP校验和。 如果你要处理那些自己它变得更加痛苦。 (如果没有你的平台上工作,你可能做......要么,还是我搞砸了别的东西OS X修复我并自动将您的平台没有。)
import socket
import struct
def make_ip(proto, srcip, dstip, ident=54321):
saddr = socket.inet_aton(srcip)
daddr = socket.inet_aton(dstip)
ihl_ver = (4 << 4) | 5
return struct.pack('!BBHHHBBH4s4s' ,
ihl_ver, 0, 0, ident, 0, 255, proto, 0, saddr, daddr)
def make_tcp(srcport, dstport, payload, seq=123, ackseq=0,
fin=False, syn=True, rst=False, psh=False, ack=False, urg=False,
window=5840):
offset_res = (5 << 4) | 0
flags = (fin | (syn << 1) | (rst << 2) |
(psh <<3) | (ack << 4) | (urg << 5))
return struct.pack('!HHLLBBHHH',
srcport, dstport, seq, ackseq, offset_res,
flags, window, 0, 0)
srcip = dstip = '127.0.0.1'
srcport, dstport = 11001, 11000
payload = '[TESTING]\n'
ip = make_ip(socket.IPPROTO_TCP, srcip, dstip)
tcp = make_tcp(srcport, dstport, payload)
packet = ip + tcp + payload
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
s.sendto(packet, (dstip, 0))
response, addr = s.recvfrom(65535)
response_id = struct.unpack('!H', response[4:6])
print response_id
每次我跑,我得到一个NAK(如果端口11000没有一个人听)或ACK报文,随机IP_ID
,正如你所期望的。