Python的网络编程[3] -> BOOTP 协议[1] -> BOOTP 的 Python 实现
BOOTP实现 / BOOTP Implement
目录
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 实现部分内容
import socket
import struct
import os
from BOOTP_CodeC import ServerCodeC
SERVERNAME = 'Bootpserver' class BOOTPServer():
def __init__(self):
self.server_ip = '127.0.0.1'
self.offer_ip = '127.0.0.8'
self.server_port = 68 # Respond client via this port
self.client_port = 67 # Receive client data via this port
self.send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.send_sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, True)
self.send_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
#self.send_sock.bind((self.server_ip, self.client_port))
self.file_bin = ['secondboot.b3', 'files4.rc'] def requestCheck(self, m):
if not (
m['op'] == b'\x01' and # OP
m['htype'] == b'\x01' and # HTYPE
m['hlen'] == b'\x06' and # HLEN
m['hops'] == b'\x00' and # HOPS
m['secs'] == [b'\x00', b'\x00'] and # SECS
m['flags'] == [b'\x80', b'\x00'] and # FLAGS (broadcast)
m['ciaddr'] == '0.0.0.0' and # Client IP Address
m['yiaddr'] == '0.0.0.0' and # Your Client IP Address
m['siaddr'] == '0.0.0.0' and # Server IP
m['giaddr'] == '0.0.0.0' # Gateway IP
):
return False
if not (
m['sname'] == SERVERNAME or
m['sname'] == ''):
return False
return True def server_start(self):
file_index = 0
while True:
if file_index >= len(self.file_bin):
break
self.rec_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.rec_sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, True)
self.rec_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
self.rec_sock.bind(('', self.client_port))
print('=== Waiting for packet')
msg, addr = self.rec_sock.recvfrom(1024)
msgBody = ServerCodeC.collect(msg)
print('<<< RECV from %s, client ip is %s, xid: %s, mac id: %s' %
(addr, msgBody['ciaddr'], msgBody['xid'], msgBody['chaddr']))
if self.requestCheck(msgBody):
print('=== This is a valid message')
offer = ServerCodeC.offer(transaction_id=msgBody['xid'],
client_ip_offer=self.offer_ip,
server_ip=self.server_ip,
client_mac_id=msgBody['chaddr'],
file_path=self.file_bin[file_index])
self.send_sock.sendto(offer, ('<broadcast>', 68))
print('>>> SEND ("<broadcast>", 68), offer ip "%s", file name is "%s"' %
(self.offer_ip, self.file_bin[file_index]))
file_index += 1
print('=== BOOTP server exit') server = BOOTPServer()
server.server_start()
2 BOOTP 的客户端建立过程
客户端建立步骤主要有:
(1) 客户端ip未知,服务端口68,客户端口67;
(2) 建立主循环,建立socket/UDP,广播模式允许复用,监听服务端端口;
(3) 广播模式朝客户端口67发送请求报文,请求报文中填入客户端信息,如xid,mac_id等,并等待接收回复报文;
(4) 进行接收等待,若未超时且受到有效报文,则对有效报文进行解码;
(5) 解码报文获取相应信息,确认xid,mac_id与发送时的是否匹配;
(6) 提取报文信息,为后续(TFTP下载启动文件)做准备;
import socket
import binascii
import struct
from BOOTP_CodeC import ClientCodeC class BOOTPClient():
def __init__(self):
self.client_ip = '0.0.0.0'
self.broadcast_ip = '255.255.255.255' # or '<broadcast>'
self.server_ip = '127.0.0.1'
self.target_port = 67
self.source_port = 68
ClientCodeC.get_xid_macid() def recv_check(self, m):
if not (
m['op'] == b'\x02' and # OP
m['htype'] == b'\x01' and # HTYPE
m['hlen'] == b'\x06' and # HLEN
m['hops'] == b'\x00' and # HOPS
m['secs'] == [b'\x00', b'\x00'] and # SECS
m['flags'] == [b'\x80', b'\x00'] and # FLAGS (broadcast)
m['xid'] == ClientCodeC.transaction_id and
m['chaddr'] == ClientCodeC.client_mac_id and
len(m['file'])
):
return False
return True def client_request(self): while True:
self.client_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.client_sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, True)
self.client_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
self.client_sock.settimeout(5)
#self.client_sock.bind((self.server_ip, 68))
self.client_sock.bind(('', 68)) self.client_sock.sendto(ClientCodeC.request(), ('<broadcast>', self.target_port))
print('>>> SEND ("<broadcast>", %d) request command' % self.target_port)
try:
data, addr = self.client_sock.recvfrom(1024)
except socket.timeout:
print('=== BOOTP client exit')
break
msgBody = ClientCodeC.collect(data)
print('<<< RECV', addr)
if self.recv_check(msgBody):
print('=== This is a valid message')
client_ip = msgBody['yiaddr']
server_name = msgBody['sname']
file_name = msgBody['file']
server_ip = msgBody['siaddr']
print('=== Server ip: %s, server name: %s, file name: %s, get ip address: %s' %
(server_name, server_ip, file_name, client_ip))
client = BOOTPClient()
client.client_request()
相关阅读
1. BOOTP 基本理论
Python的网络编程[3] -> BOOTP 协议[1] -> BOOTP 的 Python 实现的更多相关文章
- Python的网络编程[4] -> DHCP 协议[1] -> DHCP 的 Python 实现
DHCP实现 / DHCP Implement 目录 DHCP 服务器建立过程 DHCP 报文加码实现过程 下面介绍建立一个简单的DHCP服务器,主要用于对基本的DHCP请求进行响应,目前只提供一个I ...
- Python的网络编程[2] -> TFTP 协议[1] -> TFTP 的 Python 实现
TFTP实现 / TFTP Implement 目录 TFTP 的服务器建立过程 TFTP 的客户端建立过程 1 TFTP 的服务器建立过程 服务器建立步骤主要有: (1) 设定服务器IP和 ...
- Python的网络编程[4] -> DHCP 协议[0] -> DHCP 的基本理论
DHCP协议 / DHCP Protocol 目录 DHCP 基本理论 DHCP 通信流程 DHCP 完整报文 DHCP 的 Optional 字段 DHCP 的报文类型 1 DHCP 基本理论 DH ...
- Python的网络编程[6] -> Modbus 协议 -> Modbus 的基本理论与 Python 实现
Modbus协议 / Modbus Protocol 目录 Modbus 协议简介 Modbus RTU协议 Modbus TCP协议与 Python 实现 Modbus 功能码 Modbus TCP ...
- Python的网络编程[1] -> FTP 协议[0] -> FTP 的基本理论
FTP协议 / FTP Protocol FTP全称为File Transfer Protocol(文件传输协议),常用于Internet上控制文件的双向传输,常用的操作有上传和下载.基于TCP/IP ...
- Python的网络编程[2] -> TFTP 协议[0] -> TFTP 的基本理论
TFTP 的基本理论 目录 通信流程 数据报文格式 传输终结 异常处理 数据丢失和超时 TFTP(Trivial File Transfer Protocol,简单文件传输协议)是UDP协议族中的一个 ...
- Python的网络编程[1] -> FTP 协议[2] -> 使用 ftplib 建立 FTP 客户端
使用 ftplib 建立 FTP 客户端 用于建立FTP Client,与 pyftplib 建立的 Server 进行通信. 快速导航 1. 模块信息 2. 建立 FTP 客户端 1. 模块信息 1 ...
- Python的网络编程[1] -> FTP 协议[1] -> 使用 pyftplib 建立 FTP 服务器
使用 pyftplib 建立 FTP 服务器 pyftplib 主要用于建立 FTP Server,与 ftplib 建立的 Client 进行通信. 快速导航 1. 模块信息 2. 建立 FTP 服 ...
- python之网络编程
本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 共享内存(匿名的和具名的) 远程过程调用 ...
- Python高级网络编程系列之第一篇
在上一篇中我们简单的说了一下Python中网络编程的基础知识(相关API就不解释了),其中还有什么细节的知识点没有进行说明,如什么是TCP/IP协议有几种状态,什么是TCP三次握手,什么是TCP四次握 ...
随机推荐
- 《Cracking the Coding Interview》——第11章:排序和搜索——题目3
2014-03-21 20:55 题目:给定一个旋转过的升序排序好的数组,不知道旋转了几位.找出其中是否存在某一个值. 解法1:如果数组的元素都不重复,那么我的解法是先找出旋转的偏移量,然后进行带偏移 ...
- 恢复误删除表黑科技之relay log大法
Preface In my previous blogs,I've demonstrated several mothods of how to rescue a dropped ta ...
- day06_05 字典
1.0 字典 1.1 补充知识:用id可以查找出变量的内存地址 a = 10 print(id(a)) #找出内存地址 #>>>506528496 b = 15 print(id(b ...
- PAT——甲级1042:Shuffling Mashine
终于做到甲级了 就一个感觉....题目是真的看不懂,亏我还是四六级都过了的人....可是看完题愣是一点都不懂是什么意思. 1042 Shuffling Machine (20 point(s)) Sh ...
- URAL 1684. Jack's Last Word ( KMP next函数应用 )
题意:问第二行的串能不能恰好分割成几个串,使得这几个串都是第一行串的前缀.如果是,输出No, 并输出这几个串,否则输出Yes. 这题是Special Judge,把两个串连接起来,中间用一个未出现过的 ...
- Codeforces Round #327 (Div2) A~E
CodeForces 591A 题意:在距离为L的两端A,B,相向发射魔法,a(以P1的速度)-->B,A<--b(以P2的速度).假设a-->B,途中相遇,则返回到原点A<- ...
- 软工实践Alpha冲刺(7/10)
队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 已经解决登录注册等基本功能的界面. 完成非功能的主界面制作 ...
- 【bzoj1875】[SDOI2009]HH去散步 矩阵乘法
题目描述 一张N个点M条边的无向图,从A走到B,要求:每一次不能立刻沿着上一次的边的反方向返回.求方案数. 输入 第一行:五个整数N,M,t,A,B. N表示学校里的路口的个数 M表示学校里的路的条数 ...
- 【bzoj3894】文理分科 网络流最小割
原文地址:http://www.cnblogs.com/GXZlegend 题目描述 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过) 小P所在的班级要进行文理分科.他的班级可以用 ...
- Codeforces Round #306 (Div. 2) 550A Two Substrings
链接:http://codeforces.com/contest/550/problem/A 这是我第一次玩cf这种比赛,前面做了几场练习,觉得div2的前面几个还是比较水的. 所以看到这道题我果断觉 ...