zoukankan      html  css  js  c++  java
  • Python的网络编程[3] -> BOOTP 协议[1] -> BOOTP 的 Python 实现

    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 基本理论

  • 相关阅读:
    网络攻击与防御 实验1
    java继承 、方法重写、重写toString方法
    递归算法
    加标签的continue用法
    程序员,你应该知道的数据结构之栈
    SpringBoot 内部方法调用,事务不起作用的原因及解决办法
    程序员,你应该知道的数据结构之哈希表
    程序员,你应该知道的数据结构之跳表
    程序员,你应该知道的二分查找算法
    程序员,你应该知道的基础排序算法
  • 原文地址:https://www.cnblogs.com/stacklike/p/8149737.html
Copyright © 2011-2022 走看看