一、socket函数
1、socket函数参数及方法
1)参数
Python 中,用 socket()函数来创建套接字,语法格式如下
socket.socket([family[, type[, proto]]])
· family: 套接字家族可以使 AF_UNIX 或者 AF_INET。
· type: 套接字类型可以根据是面向连接的还是非连接分为 SOCK_STREAM 或 SOCK_DGRAM。
· protocol: 一般不填默认为 0。
https://gist.github.com/kevinkindom/108ffd675cb9253f8f71
2)方法
https://www.runoob.com/python/python-socket.html
2、TCP/UDP通讯
该方法自动补充MAC、IP、TCP包头,意味着我们需要填充的是包结构图中的 [ 数据 ]
1)send_udp_tcp.py
import argparse
import socket
parser = argparse.ArgumentParser(description='Client')
parser.add_argument('--TCP_UDP', type=str, default='UDP')
parser.add_argument('--src_ip', type=str, default='172.16.200.1')
parser.add_argument('--dst_ip', type=str, default='172.16.200.2')
parser.add_argument('--dst_port', type=int, default=31500)
parser.add_argument('--send_times', type=int, default=10)
args = parser.parse_args()
if args.TCP_UDP == 'UDP':
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# s.bind((args.src_ip,0)) # in windows
s.setsockopt(socket.SOL_SOCKET, 25, 'ens3f0'.encode(encoding="utf-8")) # in linux
print("now using:"+str(args.TCP_UDP))
print("src_ip:"+str(args.src_ip))
print("dst_ip:"+str(args.dst_ip))
print("dst_port:"+str(args.dst_port))
print("send_times"+str(args.send_times))
print("send data begin")
for i in range(args.send_times):
s.sendto("test udp".encode(encoding="utf-8"), (args.dst_ip, args.dst_port))
print("send ok")
s.close()
elif args.TCP_UDP == 'TCP' : # TCP尚未测试
print("now using:"+str(args.TCP_UDP))
print("src_ip:"+str(args.src_ip))
print("dst_ip:"+str(args.dst_ip))
print("dst_port:"+str(args.dst_port))
print("send_times"+str(args.send_times))
print("send data begin")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((args.dst_ip, args.dst_port))
except Exception:
print("server port not connect!")
for i in range(args.send_times):
s.send('test tcp')
print("send ok")
s.close()
else:
print("error TCP/UDP type")
2)recv_udp_tcp.py
import argparse
import socket
parser = argparse.ArgumentParser(description='Server')
parser.add_argument('--TCP_UDP', type=str, default='UDP')
parser.add_argument('--my_ip', type=str, default='172.16.200.2')
parser.add_argument('--my_port', type=int, default=31500)
args = parser.parse_args()
if args.TCP_UDP == 'UDP':
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((args.my_ip, args.my_port))
print("now using:"+str(args.TCP_UDP))
print("my_ip:"+str(args.my_ip))
print("my_port:"+str(args.my_port))
print("recv data begin")
while True:
data, addr = s.recvfrom(2048)
datas = str(data,encoding='utf-8')
print("received:" + datas + "\n")
# print("received:" + data + "\nfrom:" + addr)
s.close()
elif args.TCP_UDP == 'TCP' : # TCP尚未测试
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((args.my_ip, args.my_port))
print("now using:"+str(args.TCP_UDP))
print("my_ip:"+str(args.my_ip))
print("my_port:"+str(args.my_port))
print("recv data begin")
s.listen(5)
ss, addr = s.accept() # 被动接受TCP客户端连接,(阻塞式)等待连接的到来
print('got connected from',addr)
ra = ss.recv(512)
print(ra)
ss.close()
s.close()
else:
print("error TCP/UDP type")
3、自行构造数据包
1)自行构造TCP部分及后面数据
意味着我们需要填充的是包结构图中的 [ TCP包头 | 数据 ]
需要使用RAW SOCKET 通信,AF_INET表示使用IPv4协议(自动补充以太网和IPv4部分),socket.SOCK_RAW指TCP及后面自行构造,NGA_TYPE指IPv4部分协议类型,6表示下一个部分为TCP,17表示下一个部分为UDP,一般自行构造NGA_TYPE=18
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, NGA_TYPE)
nga = struct.pack( # ngaa包头部分
'!IbbIbI', # I 表示unsigned int(4byte), b表示signed char(1byte), !表示顺序解析
worker_id,
degree,
0,
aggindex,
switch_id,
sequence + pkt_id
)
s.sendto(nga, (self.dst_ip, 0))
2)自行构造IP部分及以后
也即是说,需要填充的是上图中的 [ IP包头 | TCP包头 | 数据 ] 的内容
socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))
3)完全自行构造
意味着我们需要填充的是上图中的 [ MAC包头 | IP包头 | TCP包头 | 数据 ] 的内容
socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))
4、指定网卡
二、参考资料
https://www.cnblogs.com/JenningsMao/p/9487465.html