本文目录一览:
用python篡改icmp报文再发送给接收方
程序处理上有些问题,建议深入研究一下ICMP协议。下面是Python 3的一个ICMP的简单实现,可以参考一下。
import socket
import struct
def checksum(source_string):
sum = 0
countTo = (len(source_string)/2)*2
count = 0
while countcountTo:
thisVal = ord(source_string[count + 1:count + 2])*256 + ord(source_string[count:count + 1])
sum = sum + thisVal
sum = sum 0xffffffff
count = count + 2
if countTolen(source_string):
sum = sum + ord(source_string[len(source_string) - 1])
sum = sum 0xffffffff
sum = (sum 16) + (sum 0xffff)
sum = sum + (sum 16)
answer = ~sum
answer = answer 0xffff
answer = answer 8 | (answer 8 0xff00)
return answer
def ping(ip):
rawsocket1=socket.socket(socket.AF_INET,socket.SOCK_RAW, socket.getprotobyname('icmp'))
packet = struct.pack('!BBHHH8s', 8, 0, 0, 0, 0, b'abcdefgh')
chksum=checksum(packet)
packet = struct.pack('!BBHHH8s', 8, 0, chksum, 0, 0, b'abcdefgh')
rawsocket1.sendto(packet, (ip, 1))
ping('10.172.23.254')
python基础(21)-线程通信
到这里,我们要聊一下线程通信的内容;
首先,我们抛开语言不谈,先看看比较基础的东西,线程间通信的方式;其实也就是哪几种(我这里说的,是我的所谓的知道的。。。)事件,消息队列,信号量,条件变量(锁算不算?我只是认为是同步的一种);所以我们也就是要把这些掌握了,因为各有各的好处嘛;
条件变量我放到了上面的线程同步里面讲了,我总感觉这算是同步的一种,没有很多具体信息的沟通;同时吧,我认为条件变量比较重要,因为这种可以应用于线程池的操作上;所以比较重要;这里,抛开条件变量不谈,我们看看其他的东西;
1、消息队列:
queue 模块下提供了几个阻塞队列,这些队列主要用于实现线程通信。在 queue 模块下主要提供了三个类,分别代表三种队列,它们的主要区别就在于进队列、出队列的不同。
关于这三个队列类的简单介绍如下:
queue.Queue(maxsize=0):代表 FIFO(先进先出)的常规队列,maxsize 可以限制队列的大小。如果队列的大小达到队列的上限,就会加锁,再次加入元素时就会被阻塞,直到队列中的元素被消费。如果将 maxsize 设置为 0 或负数,则该队列的大小就是无限制的。
queue.LifoQueue(maxsize=0):代表 LIFO(后进先出)的队列,与 Queue 的区别就是出队列的顺序不同。
PriorityQueue(maxsize=0):代表优先级队列,优先级最小的元素先出队列。
这三个队列类的属性和方法基本相同, 它们都提供了如下属性和方法:
Queue.qsize():返回队列的实际大小,也就是该队列中包含几个元素。
Queue.empty():判断队列是否为空。
Queue.full():判断队列是否已满。
Queue.put(item, block=True, timeout=None):向队列中放入元素。如果队列己满,且 block 参数为 True(阻塞),当前线程被阻塞,timeout 指定阻塞时间,如果将 timeout 设置为 None,则代表一直阻塞,直到该队列的元素被消费;如果队列己满,且 block 参数为 False(不阻塞),则直接引发 queue.FULL 异常。
Queue.put_nowait(item):向队列中放入元素,不阻塞。相当于在上一个方法中将 block 参数设置为 False。
Queue.get(item, block=True, timeout=None):从队列中取出元素(消费元素)。如果队列已满,且 block 参数为 True(阻塞),当前线程被阻塞,timeout 指定阻塞时间,如果将 timeout 设置为 None,则代表一直阻塞,直到有元素被放入队列中; 如果队列己空,且 block 参数为 False(不阻塞),则直接引发 queue.EMPTY 异常。
Queue.get_nowait(item):从队列中取出元素,不阻塞。相当于在上一个方法中将 block 参数设置为 False。
其实我们想想,这个队列,是python进行封装的,那么我们可以用在线程间的通信;同时也是可以用做一个数据结构;先进先出就是队列,后进先出就是栈;我们用这个栈写个十进制转二进制的例子:
没毛病,可以正常的打印;其中需要注意的就是,maxsize在初始化的时候如果是0或者是个负数的话,那么就会是不限制大小;
那么其实我们想想,我们如果用做线程通信的话,我们两个线程,可以把队列设置为1的大小,如果是1对多,比如是创建者和消费者的关系,我们完全可以作为消息队列,比如说创建者一直在创建一些东西,然后放入到消息队列里面,然后供消费着使用;就是一个很好的例子;所以,其实说是消息队列,也就是队列,没差;
=====================================================================
下面来看一下事件
Event 是一种非常简单的线程通信机制,一个线程发出一个 Event,另一个线程可通过该 Event 被触发。
Event 本身管理一个内部旗标,程序可以通过 Event 的 set() 方法将该旗标设置为 True,也可以调用 clear() 方法将该旗标设置为 False。程序可以调用 wait() 方法来阻塞当前线程,直到 Event 的内部旗标被设置为 True。
Event 提供了如下方法:
is_set():该方法返回 Event 的内部旗标是否为True。
set():该方法将会把 Event 的内部旗标设置为 True,并唤醒所有处于等待状态的线程。
clear():该方法将 Event 的内部旗标设置为 False,通常接下来会调用 wait() 方法来阻塞当前线程。
wait(timeout=None):该方法会阻塞当前线程。
这里我想解释一下;其实对于事件来说,事件可以看成和条件变量是一样的,只是我们说说不一样的地方;
1、对于事件来说,一旦触发了事件,也就是说,一旦set为true了,那么就会一直为true,需要clear调内部的标志,才能继续wait;但是conditon不是,他是一次性的唤醒其他线程;
2、conditon自己带锁;事件呢?不是的;没有自己的锁;比如说有一个存钱的线程,有一个是取钱的线程;那么存钱的线程要存钱;需要怎么办呢?1、发现银行没有钱了(is_set判断);2、锁住银行;3、存钱;4、释放银行;5、唤醒事件;对于取钱的人;1、判断是否有钱;2、被唤醒了,然后锁住银行;3、开始取钱;4、清理告诉存钱的人,我没钱了(clear);5、释放锁;6、等着钱存进去;
其实说白了,就是记住一点;这个旗标需要自己clear就对了
写个例子,怕以后忘了怎么用;
其实时间和信号量比较像;但是信号量不用自己清除标志位;但是事件是需要的;
如何用python实现串口通信
Python非常适合写一些测试的脚本,如快速的串口通信测试等。如果使用VC++ QT开发,可能用时较多,使用python,如果掌握使用方法,可以直接读写测试,配合设备或是串口助手,很快验证与实现。
Python有没有现成的串口API直接调用呢?经过实践验证,需要安装一个叫 Pyserial的组件即可。这个可以在github上下载。
在windows 7 64bit 上可以使用吗?当然可以使用,我安装的python3.5为64位的。把下载后的文件,其中有一个serial的文件夹,拷贝到python35安装路径, C:\Python35\Lib\site-packages\serial
网上可以搜一下windows的安装包,安装完也是:C:\Python35\Lib\site-packages\serial ,可以用最新的版本,替换即可。
测试的方法:在python IDE里测试:
import serial
这里如果报错,是python版本与pyserial版本没有配合好。如果正常,不返回,即可以导入serial模块。
ser=serial.Serial("COM5",115200)
这里为COM5,115200的波特率。如果打不开,请检查安装环境。
ser.write('hello,serial test'.encode())
17
发送测试(如果返回字节数,说明返回成功),这里需要转换一个编码为字节。
以上测试,可以使用现在的设备或是串口助手,如安装Virtual Serial Port Driver 7.2 虚拟串口软件,设置一对串口,进行自发自收的测试。
print(ser.readline())
b'abcdefg\r\n'
这里是串口接收,有接收的超时。设备或是串口助手发送一个字符串,以回车换行结束,这里就可以收到打印出来。
也可以用ser.read(),这里只接收一个字符来实现。
上面已经实现了基本的串口操作。
关闭串口为:
ser.close()
如果使用python,一般写个py文件,就像windows bat 批处理一样,这是python强大的地方。如果写一个py脚本呢?其实只要把上面的命令,一条条写下来,就是一个脚本,测试如下:
import serialser=serial.Serial("COM5",115200,timeout=0.5)for i in range(0,100-1):ser.write('hello\r\n'.encode())print(ser.readline());ser.close()