DHCP(Dynamic Host Configuration Protocol,动态主机配置协议),前身是BOOTP协议,是一个局域网的网络协议,使用UDP协议工作,统一使用两个IANA分配的端口:67(服务器端),68(客户端)。主要作用是集中的管理、分配IP地址,使client动态的获得IP地址、Gateway地址、DNS服务器地址等信息。
option字段
DHCP报文中的Options字段可以用来存放普通协议中没有定义的控制信息和参数。如果用户在DHCP服务器端配置了Options字段,DHCP客户端在申请IP地址的时候,会通过服务器端回应的DHCP报文获得Options字段中的配置信息。
获取IP地址过程
实验使用的linux 主机由两个网络接口,其中ens33使用DHCP获取IP地址,ens37使用静态IP地址;因此需要使用ens33来发送数据包。
Change_MACpy用于MAC地址与Bytes类型相互转换。
DHCP_Discoverpy用于发送DHCP Discover报文;其中GET_MACpy见ARP章节。
DHCP_Requestpy用于发送DHCP Request报文。
DHCP_FULLpy用于完成DHCP Client与DHCP Server的报文交互
Wireshark对远程linux主机抓包,结果如下
客户端以广播发送DHCP Discover包,其中报文 *** 作类型为1(请求报文),DHCP客户端的MAC地址设置为00:0c:29:03:a1:08,option53设置报文类型为Discover,option55(请求选项列表)中包含请求的参数。
服务器以单播向客户端回复信息,其中报文 *** 作类型为2(应答报文),分配给客户端的IP为192168160146,option 53设置报文类型为offer,Option 54设置服务器标识为192168160254,其他option为客户端请求列表的应答。
值得注意的是,交互的四个报文中Transaction ID均为0x00000000,表明是同一次DHCP交互报文。
首先给出一个c函数的原型:int sscanf(const char buffer,const char format,[argument ])它的返回值是参数的数据,也就是argument的个数,buffer:存储的数据,format:格式控制字符串,argument:选择性设定字符串。这个程序从标准流读取数据,可以进行无限制的输入。下面贴出代码,然后引出另外一个问题,将字符串ip转换成整形ip地址。[cpp]
#include<stdioh
#include<stringh
int main(void){
char str[32];
int a,b,c,d;int ret=0;
while(fgets(str,sizeof(str),stdin)!=NULL){
int len=strlen(str);
str[len]='\0';
ret=sscanf(str,%d%d%d%d,&a,&b,&c,&d);
if(ret==4&&(a=0&&a<=255)&&(b=0&&b<=255)&&(c=0&&c<=255)&&(d=0&&d<=255)){
printf(it is ip!\n);}else
printf(it is not ip!\n);}return 0;}gcc -Wall ipc -o ip12345
下面来引出另外一个问题,在很多情况下,要求把字符串ip转换成整形ip,这个问题也可以应用sscanf这个函数,首先把四个字段存储到a,b,c,d四个变量当中去,然后进行移位运算,因为ip地址是32位的,而且是无符号整形变量,所以可以应用unsigned int 来存储 unsinged int ip=(a<<24)+(b<<16)+(c<<8)+d。
300万条不是很多。你可以使用字典,或者是Counter来统计。
通常来讲字典大小略大的时候,效率会很低。所以就要优化算法。
如果想避开字典限制的问题,可以使用redis来记数。速度慢些。但是很靠谱。
处理速度取决于进程数量,如果多进程处理,最后再将数据合并就会快很多。如果使用REDI就不用合并了。REDIS可以采用多进程加多线程方式。
如果还想更快就采用CYTHON,或者是直接用MAP REDUCE,采用多计算机同时处理。绝对快。
还有一个更简单快速的办法,用C语言吧。将IP地址转换成整数。然后用C语言来记数,绝对快。编程也简单。转成整数的方法对于PYTHON也有效。
ipaddress 模块包括用于处理 IPv4 和 IPv6 网络地址的类。这些类支持验证,查找网络上的地址和主机以及其他常见 *** 作。
最基本的对象代表网络地址本身。传递字符串,整数或字节序列给 ip_address() 来构造地址。返回值是 IPv4Address 或 IPv6Address 实例,具体取决于所使用的地址类型。
还可以用这个方法来校验 IP 地址是否合法:
网络是由一系列地址组成的,通常用地址和掩码这种形式来表示。
与地址一样,IPv4 和 IPv6网络有两种网络类。每个类提供用于访问与网络相关联的值的属性或方法,例如广播地址和可供主机使用的网络上的地址。
网络实例是可迭代的,并产生网络上的地址。
此示例仅打印一些地址,因为 IPv6 网络可以包含的地址远多于输出中的地址。
迭代网络会产生地址,但并非所有地址都对主机有效。例如,网络的基地址和广播地址。要查找网络上常规主机可以使用的地址,请使用 hosts() 方法,该方法会生成一个生成器。
将此示例的输出与前一示例进行比较表明,主机地址不包括在整个网络上进行迭代时生成的第一个值。
除了迭代器协议之外,网络还支持 in *** 作,来确定地址是否是网络的一部分。
in 使用网络掩码来测试地址,因此它比扩展网络上的完整地址列表更有效。
网络接口表示网络上的特定地址,并且可以由主机地址和网络前缀或网络掩码表示。
接口对象具有分别访问完整网络和地址的属性,以及表达接口和网络掩码的几种不同方式。
相关文档:
>
源站路由可以事先规定IP数据包所经过得路由器,每经过一个路由器就改变数据包的目的地址(下一跳)
使用IP头部中的option字段记录路由IP。该字段最大40字节,因此最多存放9个IP,记录格式如下:
Type :占1字节,code 的值此处设为137。
length :占1字节,记录整个选项的长度。
pointer :指针项,占1个字节,指向下一个被处理的源站地址,最小值为4。
发送主机从应用程序接收源站路由清单,最后一个表项(它是数据报的最终目的地址),剩余的为所有经过的下一跳,每经过一个设备都会检查是否是最终目标,如不是则从列表中读取下一项作为数据包下一跳的目的地址,同时数据包每从一个路由器发出,就记录其出接口的地址,用其替换掉清单中的上一跳地址,数据包返回时任然按照原来的路径返回。
如下图,主机S上的发送应用程序发送一份数据报给D,指定源路由为R1,R2和R3。#表示指针字段,其值分别是4、8、12和16(一个值表示一个32位IP)。长度字段恒为1 5(三个IP地址加上三个字节首部)。可以看出,每一跳IP数据报中的目的地址都发生改变。
首先知道自己的IP,然后构造这个网段内的IP,使用list来构建。
使用前需要注意27中对dict和list的处理。list是没有keys的
需要注意对ip的split *** 作来判断,split后来判断输入的Ip范围,可以用掩码的形式来进行范围确认。
传入参数的处理,这个还不完善,需要对输入的ip段和端口段进行判断,然后进行扫描。
超时时间的处理
因为在测试过程中有的设备没有在线设备,需要设置socket去connect的timeout时间,而且这个设置必须在connect之前进行,否则不生效。
以上就是关于Python网络编程5-实现DHCP Client全部的内容,包括:Python网络编程5-实现DHCP Client、python中判断一个字符串是否是IP地址、用python处理一含有300万条ip地址的文本,需得出每个ip在文本中重复的次数。得到一个ip , 次数的文本。等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)