欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python 之 并发编程(非阻塞IO模型、I/O多路复用、socketserver的使用)

程序员文章站 2022-11-08 13:56:24
9.16 非阻塞IO模型 cpu占用率过高 服务端: 客户端; 9.17 I/O多路复用 服务端: from socket import * import select s = socket() s.bind(('127.0.0.1',8080)) s.listen(5) s.setblocking ......

9.16 非阻塞io模型

cpu占用率过高

服务端:

from socket import *
import time
s = socket()
s.bind(('127.0.0.1',8080))
s.listen(5)
s.setblocking(false)    #使accept接收不到连接时不在阻塞
​
r_list=[]
while true:
    try:
        conn, addr = s.accept()
        r_list.append(conn)
    except blockingioerror:
        # time.sleep(3)
        #print('可以去干其他的活了')
        #print('rlist: ',len(r_list))
        for conn in r_list:
            try:
                data=conn.recv(1024)
                conn.send(data.upper())
            except blockingioerror:
                continue

客户端;

from socket import *
import os
client = socket()
client.connect(('127.0.0.1', 8080))
​
while true:
    data='%s say hello' %os.getpid()
    client.send(data.encode('utf-8'))
    res=client.recv(1024)
    print(res.decode('utf-8'))

9.17 i/o多路复用

服务端:

from socket import *
import select
s = socket()
s.bind(('127.0.0.1',8080))
s.listen(5)
s.setblocking(false)                        #使accept接收不到连接时不在阻塞
# print(s)
​
r_list=[s,]
w_list=[]
w_data={}
while true:
    print('被检测r_list: ',len(r_list))
    print('被检测w_list: ',len(w_list))      #rl中是r_list中建立连接的套接字对象
    rl,wl,xl=select.select(r_list,w_list,[],) #r_list=[server,conn]
    # print('rl: ',len(rl)) #rl=[conn,]
    # print('wl: ',len(wl))
​
    # 收消息
    for r in rl: #r=conn
        if r == s:
            conn,addr=r.accept()
            r_list.append(conn)
        else:
            try:
                data=r.recv(1024)
                if not data:
                    r.close()
                    r_list.remove(r)
                    continue
                # r.send(data.upper())
                w_list.append(r)
                w_data[r]=data.upper()
            except connectionreseterror:
                r.close()
                r_list.remove(r)
                continue
    # 发消息
    for w in wl:
        w.send(w_data[w])
        w_list.remove(w)
        w_data.pop(w)

客户端:

from socket import *
import os
client = socket()
client.connect(('127.0.0.1', 8080))
​
while true:
    data='%s say hello' %os.getpid()
    client.send(data.encode('utf-8'))
    res=client.recv(1024)
    print(res.decode('utf-8'))

9.18 socketserver的使用

9.181 基于tcp的socketserver

服务端:

import socketserver
# 通信循环
class mytcphandler(socketserver.baserequesthandler):
    def handle(self):
        while true:
            try:
                data = self.request.recv(1024)  # 1024 接收数据的最大限制
                if not data: break  # 针对linux系统
                self.request.send(data.upper())  # 注意:收发都是以bytes为单位
            except connectionreseterror:
                break
        self.request.close()
​
if __name__ == '__main__':
    #连接循环
    server=socketserver.threadingtcpserver(('127.0.0.1',8080),mytcphandler)
    server.serve_forever()
​
    print(server.server_address)
    print(server.requesthandlerclass)
    print(server.socket)

客户端:

import socket
client=socket.socket(socket.af_inet,socket.sock_stream)
client.connect(('127.0.0.1',8080))
​
while true:
    msg=input('>>: ').strip()
    client.send(msg.encode('utf-8'))
    data=client.recv(1024)
    print(data.decode('utf-8'))
client.close()

9.182 基于udp的socketserver

服务端:

import socketserver
# 通信循环
class myudphandler(socketserver.baserequesthandler):
    def handle(self):
        print(self.request)#(b'13404 hello', <socket.socket fd=460, family=addressfamily.af_inet, 
        res=self.request[0]#type=socketkind.sock_dgram, proto=0, laddr=('127.0.0.1', 8080)>)
        print('客户端发来的数据:',res)
        
        self.request[1].sendto(res.upper(),self.client_address)
​
if __name__ == '__main__':
    #连接循环
    server=socketserver.threadingudpserver(('127.0.0.1',8080),myudphandler)
    server.serve_forever()

客户端:

import socket
import os
client=socket.socket(socket.af_inet,socket.sock_dgram)
​
while true:
    msg='%s hello' %os.getpid()
    client.sendto(msg.encode('utf-8'),('127.0.0.1',8080))
​
    res,server_addr=client.recvfrom(1024)
    print(res)