• 大聊Python----SocketServer


    什么是SocketServer

    SocketServer的最主要的作用是实现发处理,也就是可以多个用户同时上传和下载文件。

    socketserver模块简化了编写网络服务器的任务。

    socketserver一共有这么几种类型

    class socketserver.TCPServer(server_address, RequestHandlerClass, bind_and_activate=True)

    这使用Internet TCP协议,该协议提供客户端和服务器之间的连续数据流。

    class socketserver.UDPServer(server_address, RequestHandlerClass, bind_and_activate=True)

    它使用数据报文,这是离散的信息包,在传输过程中可能会无序到达或丢失。参数与TCPServer相同。

    class socketserver.UnixStreamServer(server_address, RequestHandlerClass, bind_and_activate=True)
    class socketserver.UnixDatagramServer(server_address, RequestHandlerClass,bind_and_activate=True)

    这些不常用的类与TCP和UDP类相似,但是使用Unix域套接字;它们在非unix平台上不可用。参数与TCPServer相同。

    在继承关系图中有五个类,其中四个代表四种类型的同步服务器:

    +------------+
    | BaseServer |
    +------------+
    |
    v
    +-----------+ +------------------+
    | TCPServer |------->| UnixStreamServer |
    +-----------+ +------------------+
    |
    v
    +-----------+ +--------------------+
    | UDPServer |------->| UnixDatagramServer |
    +-----------+ +--------------------+

    创建一个socketserver 至少分以下几步:

      1、首先,必须通过子类化BaseRequestHandlerclass并重写其handle()方法创建一个请求处理程序类;此方法将处理传入的请求。
      2、其次,必须实例化一个服务器类,将服务器的地址和请求处理程序类传递给它。
      3、然后调用服务器对象的handle_request() orserve_forever()方法来处理一个或多个请求。
      4、最后,调用server_close()来关闭套接字

    ## server.py ##
    
    import socketserver
    
    class MyTCPHandler(socketserver.BaseRequestHandler):  # 定义MyTCPHandler这个类
        """
        The request handler class for our server.
    
        It is instantiated once per connection to the server, and must
        override the handle() method to implement communication to the
        client.
        """
    
        def handle(self):  # handel默认自父亲里面是空的 作用是什么?就是跟客户端所有操作,都是在handle里完成的,每个请求过来,都会走这里
            while True:
                try:
                    self.data = self.request.recv(1024).strip()
                    print("{} wrote:".format(self.client_address[0])) # 打印客户端的IP地址
                    print(self.data)
                    # if not self.data: # 客户端断开连接
                    #     print(self.client_address,"断开连接!")
                    #     break
                    self.request.send(self.data.upper())
                except ConnectionResetError as error:
                    print("客户端已经断开连接!",error)
                    break
    if __name__ == "__main__":
        HOST, PORT = "HW-20180425SPSL", 6969
    
        server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
        server.serve_forever()
    ## client.py ##
    
    import socket
    client = socket.socket()  # 生命socket类型 同时 生成socket连接# 对相
    client.connect(('HW-20180425SPSL',6969))  # 连接6969端口
    while True:
        msg = input(">>:").strip()
        client.send(msg.encode("utf-8"))
        data = client.recv(1024) #
        print(data.decode())
    
    
    client.close()

    显示结果:

    client.py

    server.py

    当客户端进行断开操作,那么服务端会出现什么情况呢?

    SocketServer多并发操作

    下面的程序是实现多用户在线Ftp程序

    ## client.py ##
    
    import socket
    import os
    import json
    
    class FtpClient(object):
        def __init__(self):
            self.client = socket.socket()
        def help(self):
            msg = '''
            ls
            pwd
            cd ../..
            get filename
            put filename
            '''
            print(msg)
        def connect(self,ip,port):
            self.client.connect((ip, port))
        def interactive(self):
            #self.authenticate()
            while True:
                cmd = input(">>").strip()
                if len(cmd) ==0:continue
                cmd_str = cmd.split()[0]
                if hasattr(self,"cmd_%s" % cmd_str):
                    func = getattr(self,"cmd_%s" % cmd_str)
                    func(cmd)
                else:
                    self.help()
        def cmd_put(self,*args):
            cmd_split =  args[0].split()
            if len(cmd_split) > 1:
                filename = cmd_split[1]
                if os.path.isfile(filename):
                    filesize = os.stat(filename).st_size
                    msg_dic = {
                        "action": "put",
                        "filename":filename,
                        "size": filesize,
                        "overridden":True
                    }
                    self.client.send( json.dumps(msg_dic).encode("utf-8")  )
                    print("send",json.dumps(msg_dic).encode("utf-8") )
                    #防止粘包,等服务器确认
                    server_response = self.client.recv(1024)
                    f = open(filename,"rb")
                    for line in f:
                        self.client.send(line)
                    else:
                        print("file upload success...")
                        f.close()
    
                else:
                    print(filename,"is not exist")
        def cmd_get(self):
            pass
    
    
    ftp = FtpClient()
    ftp.connect('HW-20180425SPSL', 6969)
    ftp.interactive()
    ## server.py ##
    
    import socketserver
    import json
    import os
    class MyTCPHandler(socketserver.BaseRequestHandler):
    
    
        def put(self,*args):
            '''接收客户端文件'''
            cmd_dic = args[0]
            filename = cmd_dic["filename"]
            filesize = cmd_dic["size"]
            if os.path.isfile(filename):
                f = open(filename + ".new","wb")
            else:
                f = open(filename , "wb")
    
            self.request.send(b"200 ok")
            received_size = 0
            while received_size < filesize:
                data = self.request.recv(1024)
                f.write(data)
                received_size += len(data)
            else:
                print("file [%s] has uploaded..." % filename)
    
        def handle(self):
            while True:
                try:
                    self.data = self.request.recv(1024).strip()
                    print("{} wrote:".format(self.client_address[0]))
                    print(self.data)
                    cmd_dic = json.loads(self.data.decode())
                    action = cmd_dic["action"]
                    if hasattr(self,action):
                        func = getattr(self,action)
                        func(cmd_dic)
    
                except ConnectionResetError as e:
                    print("err",e)
                    break
    if __name__ == "__main__":
        HOST, PORT = "HW-20180425SPSL", 6969
        # Create the server, binding to localhost on port 9999
        server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)
        server.serve_forever()

    结果显示:

    client:

    client(1):

    server:

  • 相关阅读:
    【PAT甲级】1063 Set Similarity (25 分)
    【PAT甲级】1062 Talent and Virtue (25 分)
    【PAT甲级】1061 Dating (20 分)
    Codeforces Global Round 5E(构造,思维)
    Codeforces Round #592 (Div. 2)G(模拟)
    POJ 刷题进程.1
    登录页面 (带遮罩层的) ---2017-04--5
    回答: 2017-03-19的关于css+div布局的疑问 2017-04-05
    关于js高度和宽度的获取 ----2017-03-29
    如何用写js弹出层 ----2017-03-29
  • 原文地址:https://www.cnblogs.com/zhuifeng-mayi/p/9263988.html
Copyright © 2020-2023  润新知