python socketserver类的应用

socketsoerver类的五大类型之间的联系:
在这里插入图片描述
日常主要用到的是以下这两个类型,但是,你会发现这两个类型,并没法实现我们要的多客户端连接,只等前一个连接结束,后一个连接才可以开始。

socketserver.TCPServer:是用于TCP连接
socketserver.UDPServer:是用于UDP连接

要想实现多客户端连接,则需要用以下两个类型

socketserver.ThreadingTCPServer:支持并发连接,即每收到一个连接请求,都会派出一个小弟(也就是创建一个线程)去连接。
ocketserver.ThreadingUDPServer:也是通过线程来实现高并发的

socketserver类的基本用法步骤:(以TCP连接为例子)

import socketserver
import subprocess
#第一步:创建一个类,该类需要继承socketserver的基础类BaseRequestHandler,
#同时,需要重写该基础类的handle()方法
class myTCPHandler(socketserver.BaseRequestHandler):
	#重写handle方法
    def handle(self):
    	#这里是实现接收跟发送的代码
        pass

if __name__=='__main__':
    host,port='localhost',9999
   #第二步:创建一个socketserver类中其中一种类型的实例
   #同时,把元组(IP,port),以及第一步创建的类,传给这个实例 
   server=socketserver.ThreadingTCPServer((host,port),myTCPHandler)
   #第三步:调用server_forever()/handle_request()方法来处理请求
    #多连接请求
    server.serve_forever()
    #server_forever()等价于socket类中以下这部分代码
    #while True:
    #	con, addr = server_sock.accept()

	#单链接请求:
    handle_request()
    #等价于socket类以下这句代码
    #con, addr = server_sock.accept()

完整例子如下:(模拟远程执行cmd命令)

#服务端
# -*-coding:utf-8 -*-
import socketserver
import subprocess
class myTCPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            self.data=self.request.recv(1024).strip()
            data=subprocess.Popen(self.data.decode('utf-8'),shell=True,stdout=subprocess.PIPE,stdin=subprocess.PIPE,stderr=subprocess.PIPE)
            stdout=data.stdout.read()
            print('----------------')
            print('输出',stdout)
            # stdin=data.stdin.read()
            stderr=data.stderr.read()
            print('异常输出',stderr)
            if len(stdout)==0:
                l=len(stderr)
                self.request.sendall(str(l).encode())
                self.request.sendall(stderr)
            else:
                l = len(stderr)
                self.request.sendall(str(l).encode())
                self.request.sendall(stdout)

if __name__=='__main__':
    host,port='localhost',9999
    server=socketserver.ThreadingTCPServer((host,port),myTCPHandler)
    server.serve_forever()
#客户端
# -*-coding:utf-8 -*-
import socket

c=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip_port=('localhost',9999)
c.connect(ip_port)
while True:
    cmd=input('cmd>>:')
    c.send(cmd.encode())
    data_len=c.recv(1024).decode('utf-8')

    print('客户端发送过来的数据长度是:'+data_len)
    i=int(data_len)/1024
    print(i)
    data=b''
    while i+1>=1:
        data+=c.recv(1024)
        i-=1
    # print(n,type(n))
    # data=c.recv(1024)
    print(data.decode('gbk'))

UDP跟TCP使用socketserver的区别;

UDP:
	接收数据: data= self.request[0]
	获取套接字对象   udp_s = self.request[1]
	获取IP_port:  add = self.client_address
TCP:
	data=self.request.recv(1024)
	直接用self.request就可以发数据,收数据

具体例子如下:

# -*-coding:utf-8 -*-
import socketserver
import subprocess
class UDPhandle(socketserver.BaseRequestHandler):
    def handle(self):

        while True:
            cmd = self.request[0]
            udp_s = self.request[1]
            add = self.client_address
            cmd_data = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdin=subprocess.PIPE, stderr=subprocess.PIPE,
                                        stdout=subprocess.PIPE)
            stderr = cmd_data.stderr.read()
            stdout = cmd_data.stdout.read()
            if not stderr:
                d = str(len(stdout))
                udp_s.sendto(d.encode(), add)
                udp_s.sendto(stdout, add)
            else:
                d = str(len(stderr))
                udp_s.sendto(d.encode(), add)
                udp_s.sendto(stderr, add)

if __name__=='__main__':
    udp_s=socketserver.ThreadingUDPServer(('localhost',1111),UDPhandle)
    udp_s.serve_forever()

客户端

# -*-coding:utf-8 -*-
import socket
udp_c=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
ip_port=('localhost',1111)
while True:
    msg=input('>>:').strip()
    if not msg:
        continue
    udp_c.sendto(msg.encode(),ip_port)
    size=int(udp_c.recv(1024))
    print(size)
    backPmsg,addr=udp_c.recvfrom(size)
    print(backPmsg.decode('gbk'))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值