码迷,mamicode.com
首页 > 编程语言 > 详细

Python的网络编程[3] -> BOOTP 协议 -> BOOTP 的 Python 实现

时间:2017-12-30 15:53:50      阅读:213      评论:0      收藏:0      [点我收藏+]

标签:http   name   ftp   offer   boot   解码   message   rom   启动   

BOOTP实现 / BOOTP Implement


目录

  1. BOOTP 的服务器建立过程
  2. BOOTP 的客户端建立过程

 Note: 理论部分请参考文末相关阅读链接

1 BOOTP 的服务器建立过程

服务器建立步骤主要有:

(1)      设定服务器IP,传送ip(offer_ip),服务端口68,客户端口67;

(2)      建立send_socket/UDP,广播模式允许复用,绑定到服务器ip,客户端端口;

(3)      建立主循环,建立recv_socket进行监听广播地址和客户端口;

(4)      Recv_socket进行广播接收,筛选收到的广播报文,对有效报文进行解码;

(5)      解码报文获取相应信息,xid,mac_id等;

(6)      加码回传报文,填入收到的xid,mac_id,server ip,offer ip, 文件名等;

(7)      利用send_socket向68端口以广播形式回复报文;

(8)      判断待传文件是否还有未传送的,是则回到循环等待下一个有效广播请求

Note: BOOTP_CodeC 中的加码实现可参考 BOOTP 加码的 Python 实现部分内容

 1 import socket
 2 import struct
 3 import os
 4 from BOOTP_CodeC import ServerCodeC
 5 SERVERNAME = Bootpserver
 6 
 7 class BOOTPServer():
 8     def __init__(self):
 9         self.server_ip = 127.0.0.1
10         self.offer_ip = 127.0.0.8
11         self.server_port = 68   # Respond client via this port
12         self.client_port = 67   # Receive client data via this port
13         self.send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
14         self.send_sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, True)
15         self.send_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
16         #self.send_sock.bind((self.server_ip, self.client_port))
17         self.file_bin = [secondboot.b3, files4.rc]
18 
19     def requestCheck(self, m):
20         if not (
21                 m[op] == b\x01 and # OP
22                 m[htype] == b\x01 and # HTYPE
23                 m[hlen] == b\x06 and # HLEN
24                 m[hops] == b\x00 and # HOPS
25                 m[secs] == [b\x00, b\x00] and # SECS
26                 m[flags] == [b\x80, b\x00] and   # FLAGS (broadcast)
27                 m[ciaddr] == 0.0.0.0 and # Client IP Address
28                 m[yiaddr] == 0.0.0.0 and # Your Client IP Address
29                 m[siaddr] == 0.0.0.0 and # Server IP
30                 m[giaddr] == 0.0.0.0  # Gateway IP
31                 ):
32             return False
33         if not (
34                 m[sname] == SERVERNAME or
35                 m[sname] == ‘‘):
36             return False
37         return True
38 
39     def server_start(self):
40         file_index = 0
41         while True:
42             if file_index >= len(self.file_bin):
43                 break
44             self.rec_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
45             self.rec_sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, True)
46             self.rec_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
47             self.rec_sock.bind((‘‘, self.client_port))
48             print(=== Waiting for packet)
49             msg, addr = self.rec_sock.recvfrom(1024)
50             msgBody = ServerCodeC.collect(msg)
51             print(<<< RECV from %s, client ip is %s, xid: %s, mac id: %s %
52                   (addr, msgBody[ciaddr], msgBody[xid], msgBody[chaddr]))
53             if self.requestCheck(msgBody):
54                 print(=== This is a valid message)
55                 offer = ServerCodeC.offer(transaction_id=msgBody[xid],
56                                           client_ip_offer=self.offer_ip,
57                                           server_ip=self.server_ip,
58                                           client_mac_id=msgBody[chaddr],
59                                           file_path=self.file_bin[file_index])
60                 self.send_sock.sendto(offer, (<broadcast>, 68))
61                 print(>>> SEND ("<broadcast>", 68), offer ip "%s", file name is "%s" %
62                       (self.offer_ip, self.file_bin[file_index]))
63                 file_index += 1
64         print(=== BOOTP server exit)
65 
66 server = BOOTPServer()
67 server.server_start()

2 BOOTP 的客户端建立过程

客户端建立步骤主要有:

(1)      客户端ip未知,服务端口68,客户端口67;

(2)      建立主循环,建立socket/UDP,广播模式允许复用,监听服务端端口;

(3)      广播模式朝客户端口67发送请求报文,请求报文中填入客户端信息,如xid,mac_id等,并等待接收回复报文;

(4)      进行接收等待,若未超时且受到有效报文,则对有效报文进行解码;

(5)      解码报文获取相应信息,确认xid,mac_id与发送时的是否匹配;

(6)      提取报文信息,为后续(TFTP下载启动文件)做准备;

 1 import socket
 2 import binascii
 3 import struct
 4 from BOOTP_CodeC import ClientCodeC
 5 
 6 class BOOTPClient():
 7     def __init__(self):
 8         self.client_ip = 0.0.0.0
 9         self.broadcast_ip = 255.255.255.255   # or ‘<broadcast>‘
10         self.server_ip = 127.0.0.1
11         self.target_port = 67
12         self.source_port = 68
13         ClientCodeC.get_xid_macid()
14 
15     def recv_check(self, m):
16         if not (
17                 m[op] == b\x02 and # OP
18                 m[htype] == b\x01 and # HTYPE
19                 m[hlen] == b\x06 and # HLEN
20                 m[hops] == b\x00 and # HOPS
21                 m[secs] == [b\x00, b\x00] and # SECS
22                 m[flags] == [b\x80, b\x00] and   # FLAGS (broadcast)
23                 m[xid] == ClientCodeC.transaction_id and
24                 m[chaddr] == ClientCodeC.client_mac_id and
25                 len(m[file])
26         ):
27             return False
28         return True
29 
30     def client_request(self):
31 
32         while True:
33             self.client_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
34             self.client_sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, True)
35             self.client_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
36             self.client_sock.settimeout(5)
37             #self.client_sock.bind((self.server_ip, 68))
38             self.client_sock.bind((‘‘, 68))
39 
40             self.client_sock.sendto(ClientCodeC.request(), (<broadcast>, self.target_port))
41             print(>>> SEND ("<broadcast>", %d) request command % self.target_port)
42             try:
43                 data, addr = self.client_sock.recvfrom(1024)
44             except socket.timeout:
45                 print(=== BOOTP client exit)
46                 break
47             msgBody = ClientCodeC.collect(data)
48             print(<<< RECV, addr)
49             if self.recv_check(msgBody):
50                 print(=== This is a valid message)
51                 client_ip = msgBody[yiaddr]
52                 server_name = msgBody[sname]
53                 file_name = msgBody[file]
54                 server_ip = msgBody[siaddr]
55                 print(=== Server ip: %s, server name: %s, file name: %s, get ip address: %s %
56                       (server_name, server_ip, file_name, client_ip))
57 client = BOOTPClient()
58 client.client_request()


相关阅读


1. BOOTP 基本理论

Python的网络编程[3] -> BOOTP 协议 -> BOOTP 的 Python 实现

标签:http   name   ftp   offer   boot   解码   message   rom   启动   

原文地址:https://www.cnblogs.com/stacklike/p/8149737.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!