python基础-UDP、进程、进程池、paramike模块
1 基于UDP套接字
1.1 介绍
udp是无连接的,是数据报协议,先启动哪端都不会报错
udp服务端
import socket sk = socket() #创建一个服务器的套接字 sk.bind() #绑定服务器套接字 while True: #服务器无限循环 cs = sk.recvfrom()/sk.sendto() # 对话(接收与发送) sk.close() # 关闭服务器套接字
udp客户端
import socket client = socket() # 创建客户套接字 while True: # 通讯循环 client.sendto()/client.recvfrom() # 对话(发送/接收) client.close() # 关闭客户套接字
1.2 基本实例
1.2.1 服务端
import socket udp_server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udp_server.bind(('127.0.0.1', 9999)) while True: data,client_addr = udp_server.recvfrom(512) print(data, client_addr) udp_server.sendto(data.upper(), client_addr)
1.2.2 客户端
import socket udp_client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) while True: msg = input('>>').strip() udp_client.sendto(msg.encode('utf-8'), ('127.0.0.1',9999)) data,server_addr = udp_client.recvfrom(512) print(data.decode('utf-8'))
1.3 udp不会粘包
udp是基于数据报协议,发送一份信息,有完整的报头的主题,不会像tcp那样基于数据流的,没有开头、没有结尾;而udp有开头(报头),也有结尾,所以不会出现像tcp那样粘包现象。
1.3.1 服务端
import socket udp_server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udp_server.bind(('127.0.0.1',9999)) info1,client_addr = udp_server.recvfrom(1) print('info1', info1) info2,client_addr = udp_server.recvfrom(512) print('info2', info2)
1.3.2 客户端
import socket udp_client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udp_client.sendto('welcome'.encode('utf-8'), ('127.0.0.1',9999)) udp_client.sendto('beijing'.encode('utf-8'), ('127.0.0.1',9999))
1.4 udp并发
1.4.1 服务端
import socketserver class MyUDPhandler(socketserver.BaseRequestHandler): def handle(self): print(self.request) self.request[1].sendto(self.request[0].upper(), self.client_address) if __name__ == '__main__': udp_server = socketserver.ThreadingUDPServer(('127.0.0.1',8080), MyUDPhandler) udp_server.serve_forever()
1.4.2 客户端
import socket udp_client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) while True: info = input('>>').strip() udp_client.sendto(info.encode('utf-8'), ('127.0.0.1',9999)) body,server_addr = udp_client.recvfrom(512) print(body.decode('utf-8'))
2 进程
2.1 介绍
进程:正在运行的一个过程或者任务,是对正在运行程序的一个抽象。
2.2 开启进程
示例1
from multiprocessing import Process import time def my_run(info): print('task <%s> is running' %info) time.sleep(0.5) print('task <%s> is done' % info) if __name__ == '__main__': process1 = Process(target = my_run, args=('mary',)) process2 = Process(target = my_run, args=('jack',)) process1.start() process2.start()
示例2
from multiprocessing import Process import time class MyMulProcess(Process): def __init__(self,name): super().__init__() self.name = name def my_run(self): print('task <%s> is runing' % self.name) time.sleep(0.5) print('task <%s> is done' % self.name) if __name__ == '__main__': process = MyMulProcess('jack') process.my_run() process.start()
2.3 并发通信
2.3.1 服务端
from multiprocessing import Pool import os import socket tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 解决Address already in use tcp_server.bind(('127.0.0.1',9999)) tcp_server.listen(5) def work(conn, addr): print(os.getpid()) print(addr) while True: try: data = conn.recv(1024) if not data:break conn.send(data.upper()) except Exception: break conn.close() if __name__ == '__main__': pool = Pool(4) while True: conn,addr = tcp_server.accept() pool.apply_async(work, args = (conn, addr)) tcp_server.close()
2.3.2 客户端
import socket tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tcp_client.connect(('127.0.0.1',9999)) while True: info = input('>>').strip() if not info:continue tcp_client.send(info.encode('utf-8')) data = tcp_client.recv(1024) print(data.decode('utf-8')) tcp_client.close()
2.4 join方法
主进程,等待子进程运行完,才执行下面内容;
p.join只能join住start开启的进程,而不能join住run开启的进程
主进程,等待p1执行结束,才执行主进程下面的内容
from multiprocessing import Process import time def work(name): print('task <%s> is runing' %name) time.sleep(0.5) print('task <%s> is done' % name) if __name__ == '__main__': process1 = Process(target = work, args=('jack',)) process2 = Process(target = work, args=('mary',)) process_list = [process1, process2] for process in process_list: process.start() for process in process_list: process.join()
2.6 守护进程
主进程代码运行完毕,守护进程就会结束
主进程创建守护进程
1.守护进程会在主进程代码执行结束后就终止
2.守护进程内无法再开启子进程,否则抛出异常。
守护进程,守护者主进程,主进程结束,守护进程随即结束;主进程代码结束后,守护进程随之结束
from multiprocessing import Process import time def work(name): print('task <%s> is runing' %name) time.sleep(0.5) print('task <%s> is done' % name) if __name__ == '__main__': p1=Process(target=work,args=('jack',)) p1.daemon = True # 必须在进程开启之前,设置为守护进程 p1.start()
重复守护进程概念,守护进程什么时间结束;在主进程代码结束,就会结束
from multiprocessing import Process import time def foo(): print("from foo start") time.sleep(0.5) print("from foo end") def bar(): print("from bar start") time.sleep(0.8) print("from bar end") if __name__ == '__main__': process1 = Process(target = foo) process2 = Process(target = bar) process1.daemon = True process1.start() process2.start() print("主进程") #打印该行则主进程代码结束,则守护进程process1应该被终止, # 可能会有process1任务执行的打印信息from foo start, # 因为主进程打印主进程时,process1也执行了,但是随即被终止
2.7 进程同步锁
核心点:保证一个进程用完一个终端,再交个另一个终端使用,独享终端,保证有序;
2.7.1 基本用法
加锁,变为串行,保证数据不会错乱;效率与错乱之间做出取舍
from multiprocessing import Process,Lock import time def work(name, mutex): mutex.acquire() print('task <%s> is runing' %name) time.sleep(0.5) print('task <%s> is done' % name) mutex.release() if __name__ == '__main__': mutex = Lock() process1 = Process(target = work, args = ('jack', mutex)) process2 = Process(target = work, args = ('mary', mutex)) process1.start() process2.start()
2.7.2 模拟购票
模拟购票,查询票的余额,不要考虑先后顺序;而到真正购票环境,需要保证一张票不被多次购买,需要加锁。
import json,time,os from multiprocessing import Process,Lock def search(): dic = json.load(open('ticket.txt')) print('