zoukankan      html  css  js  c++  java
  • socketserver

    socketserver

    SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的Socket服务端。即:每个客户端请求连接到服务器时,Socket服务端都会在服务器是创建一个“线程”或者“进程” 专门负责处理当前客户端的所有请求。

    特点:
    socketserver自带多线程、多进程

    socketserver中的两个类,可以解决两个问题:
    server类:保证一直运行提供服务(连接循环)
    request类:可以基于一个连接进行通信循环

    • 一 简单示例
    • 二 简单示例二
    • 三 模拟上传、下载功能
      • 1 客户端上传到服务端
      • 2 服务端下载到客户端

    一 简单示例

    客户端输入,服务端返回大写
    ps:基于TCP的socketserver,实现了并发

    server:

    import socketserver
    
    
    class MyFTP(socketserver.BaseRequestHandler):
        def handle(self):
            while True:
                data = self.request.recv(1024)
                self.request.send(data.upper())
    
    
    if __name__ == '__main__':
        obj = socketserver.ThreadingTCPServer(('127.0.0.1', 8484), MyFTP)
        obj.serve_forever()
    
    

    建立连接:
    1.实例化连接类socketserver.ThreadingTCPServer(('172.0.0.1',8080),FTPserver)
    执行通信循环:
    2.永远接收连接obj.serve_forever()

    通信:
    1.MyServer必须继承socketserver.BaseRequestHandler
    2.类中必须有方法handle方法
    3.self.request.recv()self.request.send()self.request.sendall())完成发送和接收数据

    client:

    import socket
    
    ip_port = ('127.0.0.1', 8484)
    sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sk.connect(ip_port)
    
    while True:
        msg = input('>>:').strip()
        if msg == '':
            continue
        sk.send(msg.encode('utf-8'))
        
        data = sk.recv(1024)
        print(data)
    

    二 简单示例二

    模拟客房服务

    server:

    import socketserver
    
    
    class MyServer(socketserver.BaseRequestHandler):
        def handle(self):
            # print(self.request, self.client_address, self.server)
            conn = self.request
            conn.sendall('欢迎致电 小红足疗,学生请按1,白领请按2,...,如需帮助请按0.'.encode('utf8'))
            Flag = True
            while Flag:
                data = conn.recv(1024)
                data = data.decode('utf8')
                if data == 'exit':
                    Flag = False
                elif data == '0':
                    conn.sendall('您的通过可能会被录音...为您上钟的是...'.encode('utf8'))
                else:
                    conn.sendall('请重新输入.'.encode('utf8'))
    
    
    if __name__ == '__main__':
        server = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyServer)
        server.serve_forever()
    
    

    client:

    import socket
    
    ip_port = ('127.0.0.1', 8080)
    sk = socket.socket()
    sk.connect(ip_port)
    sk.settimeout(5)
    
    while True:
        data = sk.recv(1024)
        print('receive:', data.decode('utf8'))
        inp = input('please input:')
        sk.sendall(inp.encode('utf8'))
        if inp == 'exit':
            break
    
    sk.close()
    

    三 模拟上传、下载功能

    基于TCP的socketserver,实现并发的上传、下砸功能

    1 客户端上传到服务端

    server:

    import socketserver
    import struct
    import json
    import subprocess
    import os
    
    class MYTCPServer(socketserver.BaseRequestHandler):
        max_packet_size = 8192
    
        coding='utf-8'
    
        file_path = os.path.dirname(os.path.dirname(__file__))
    
        server_dir='file_upload'
    
        def handle(self):
            while True:
                while True:
                    try:
                        head_struct = self.request.recv(4)
                        if not head_struct:break
    
                        head_len = struct.unpack('i', head_struct)[0]
                        head_json = self.request.recv(head_len).decode(self.coding)
                        head_dic = json.loads(head_json)
    
                        print(head_dic)
                        #head_dic={'cmd':'put','filename':'a.txt','filesize':123123}
                        cmd=head_dic['cmd']
                        if hasattr(self,cmd):
                            func=getattr(self,cmd)
                            func(head_dic)
                    except Exception:
                        break
    
        def put(self,args):
            file_path=os.path.normpath(os.path.join(
                self.file_path,
                self.server_dir,
                args['filename']
            ))
    
            filesize=args['filesize']
            recv_size=0
            print('----->',file_path)
            with open(file_path,'wb') as f:
                while recv_size < filesize:
                    recv_data=self.request.recv(self.max_packet_size)
                    f.write(recv_data)
                    recv_size+=len(recv_data)
                    print('recvsize:%s filesize:%s' %(recv_size,filesize))
    
    
    if __name__ == '__main__':
        obj = socketserver.ThreadingTCPServer(('127.0.0.1',8586),MYTCPServer)
        obj.serve_forever()
    

    client:

    import socket
    import struct
    import json
    import os
    
    
    
    class MYTCPClient:
        address_family = socket.AF_INET
    
        socket_type = socket.SOCK_STREAM
    
        allow_reuse_address = False
    
        max_packet_size = 8192
    
        coding='utf-8'
    
        request_queue_size = 5
    
        def __init__(self, server_address, connect=True):
            self.server_address=server_address
            self.socket = socket.socket(self.address_family,
                                        self.socket_type)
            if connect:
                try:
                    self.client_connect()
                except:
                    self.client_close()
                    raise
    
        def client_connect(self):
            self.socket.connect(self.server_address)
    
        def client_close(self):
            self.socket.close()
    
        def run(self):
            while True:
                inp=input(">>: ").strip()
                if not inp:continue
                l=inp.split()
                cmd=l[0]
                if hasattr(self,cmd):
                    func=getattr(self,cmd)
                    func(l)
    
    
        def put(self,args):
            cmd=args[0]
            filename=args[1]
            if not os.path.isfile(filename):
                print('file:%s is not exists' %filename)
                return
            else:
                filesize=os.path.getsize(filename)
    
            head_dic={'cmd':cmd,'filename':os.path.basename(filename),'filesize':filesize}
            print(head_dic)
            head_json=json.dumps(head_dic)
            head_json_bytes=bytes(head_json,encoding=self.coding)
    
            head_struct=struct.pack('i',len(head_json_bytes))
            self.socket.send(head_struct)
            self.socket.send(head_json_bytes)
            send_size=0
            with open(filename,'rb') as f:
                for line in f:
                    self.socket.send(line)
                    send_size+=len(line)
                    print(send_size)
                    print(line)
                else:
                    print('upload successful')
    
    client=MYTCPClient(('127.0.0.1',8586))
    client.run()
    

    2 服务端下载到客户端

    未完...

  • 相关阅读:
    VSCode 设置 CPP 代码风格
    KiCad EDA 5.1.2 使用圆形板框时出现无法走线的问题
    oracle的sql优化
    mybatis 自动生成xml文件配置
    sql循环遍历
    XML
    oracle的concat的用法
    oracle 按某个字段查询重复数据
    Xshell 4的上传与下载
    Oracle之锁
  • 原文地址:https://www.cnblogs.com/sunqim16/p/6808327.html
Copyright © 2011-2022 走看看