zoukankan      html  css  js  c++  java
  • 网络编程----socketserver多并发实现、FTP上传多并发、udp协议套接字多并发

    一、socketserver多并发                                                             

    基于tcp的套接字,关键就是两个循环,一个链接循环,一个通信循环

    socketserver模块中分两大类:server类(解决链接问题)和request类(解决通信问题)

        (1)server类

        (2)request类

        (3)继承关系

    以下述代码为例,分析socketserver源码:

    ftpserver=socketserver.ThreadingTCPServer(('127.0.0.1',8080),FtpServer)
    ftpserver.serve_forever()

        (4)查找属性的顺序:ThreadingTCPServer->ThreadingMixIn->TCPServer->BaseServer

    1. 实例化得到ftpserver,先找类ThreadingTCPServer的__init__,在TCPServer中找到,进而执行server_bind,server_active
    2. 找ftpserver下的serve_forever,在BaseServer中找到,进而执行self._handle_request_noblock(),该方法同样是在BaseServer中
    3. 执行self._handle_request_noblock()进而执行request, client_address = self.get_request()(就是TCPServer中的self.socket.accept()),然后执行self.process_request(request, client_address)
    4. 在ThreadingMixIn中找到process_request,开启多线程应对并发,进而执行process_request_thread,执行self.finish_request(request, client_address)
    5. 上述四部分完成了链接循环,本部分开始进入处理通讯部分,在BaseServer中找到finish_request,触发我们自己定义的类的实例化,去找__init__方法,而我们自己定义的类没有该方法,则去它的父类也就是BaseRequestHandler中找....

        (5)源码分析总结 

    基于tcp的socketserver我们自己定义的类中的

    1. self.server即套接字对象
    2. self.request即一个链接
    3. self.client_address即客户端地址

    基于udp的socketserver我们自己定义的类中的

    1. self.request是一个元组(第一个元素是客户端发来的数据,第二部分是服务端的udp套接字对象),如(b'adsf', <socket.socket fd=200, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0, laddr=('127.0.0.1', 8080)>)
    2. self.client_address即客户端地址

    socketserver多并发笔记:

     1 #服务端实现多并发
     2 import socketserver
     3 
     4 class FTPserver(socketserver.BaseRequestHandler):    #通讯
     5     def handle(self):
     6         print('=====>',self)
     7         print(self.request)
     8         while True:     #通信循环
     9             data=self.request.recv(1024)
    10             print(data)
    11             self.request.send(data.upper())
    12 
    13 if __name__ == '__main__':    #这里的意思是当别人将此文件(socketserver)作为模块调用时,下面的代码将不产生作用,
    14                                 #而只能是当前文件操作时下面代码才产生作用
    15     obj=socketserver.ThreadingTCPServer(('127.0.0.1',8080),FTPserver)
    16     obj.serve_forever()   #链接循环
    server
     1 import socket
     2 phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
     3 phone.connect(('127.0.0.1',8080))
     4 
     5 while True:   #通信循环
     6     msg=input('>>>: ').strip()
     7     if not msg:continue
     8     phone.send(msg.encode('utf-8'))
     9     # print('has send==========>')
    10     data=phone.recv(1024)
    11     # print('has recv==========>')
    12     print(data)
    13 
    14 phone.close()
    client

    二、FTP上传多并发                                                                      

     1 import socketserver     #导入多并发模块
     2 import struct
     3 import json
     4 import subprocess
     5 import os
     6 
     7 class MYTCPServer(socketserver.BaseRequestHandler):
     8 
     9     max_packet_size = 8192
    10 
    11     coding='utf-8'
    12     BASE_DIR=os.path.dirname(os.path.abspath(__file__))
    13 
    14     server_dir='file_upload'
    15 
    16     def handle(self):
    17         while True:
    18             try:
    19                 head_struct = self.request.recv(4)
    20                 if not head_struct:break
    21 
    22                 head_len = struct.unpack('i', head_struct)[0]
    23                 head_json = self.request.recv(head_len).decode(self.coding)
    24                 head_dic = json.loads(head_json)
    25 
    26                 print(head_dic)
    27                 #head_dic={'cmd':'put','filename':'a.txt','filesize':123123}
    28                 cmd=head_dic['cmd']
    29                 if hasattr(self,cmd):
    30                     func=getattr(self,cmd)
    31                     func(head_dic)
    32             except Exception:
    33                 break
    34 
    35     def put(self,args):
    36         file_path=os.path.normpath(os.path.join(
    37             self.BASE_DIR,
    38             self.server_dir,
    39             args['filename']
    40         ))
    41 
    42         filesize=args['filesize']
    43         recv_size=0
    44         print('----->',file_path)
    45         with open(file_path,'wb') as f:
    46             while recv_size < filesize:
    47                 recv_data=self.request.recv(self.max_packet_size)
    48                 f.write(recv_data)
    49                 recv_size+=len(recv_data)
    50                 print('recvsize:%s filesize:%s' %(recv_size,filesize))
    51 
    52 
    53 
    54 
    55 if __name__ == '__main__':
    56     obj=socketserver.ThreadingTCPServer(('127.0.0.1',8080),MYTCPServer)
    57     obj.serve_forever()
    ftp_server
     1 import socket
     2 import struct
     3 import json
     4 import os
     5 
     6 
     7 
     8 class MYTCPClient:
     9     address_family = socket.AF_INET
    10 
    11     socket_type = socket.SOCK_STREAM
    12 
    13     allow_reuse_address = False
    14 
    15     max_packet_size = 8192
    16 
    17     coding='utf-8'
    18 
    19     request_queue_size = 5
    20 
    21     def __init__(self, server_address, connect=True):
    22         self.server_address=server_address
    23         self.socket = socket.socket(self.address_family,
    24                                     self.socket_type)
    25         if connect:
    26             try:
    27                 self.client_connect()
    28             except:
    29                 self.client_close()
    30                 raise
    31 
    32     def client_connect(self):
    33         self.socket.connect(self.server_address)
    34 
    35     def client_close(self):
    36         self.socket.close()
    37 
    38     def run(self):
    39         while True:
    40             inp=input(">>: ").strip()
    41             if not inp:continue
    42             l=inp.split()
    43             cmd=l[0]
    44             if hasattr(self,cmd):
    45                 func=getattr(self,cmd)
    46                 func(l)
    47 
    48 
    49     def put(self,args):
    50         cmd=args[0]
    51         filename=args[1]
    52         if not os.path.isfile(filename):
    53             print('file:%s is not exists' %filename)
    54             return
    55         else:
    56             filesize=os.path.getsize(filename)
    57 
    58         head_dic={'cmd':cmd,'filename':os.path.basename(filename),'filesize':filesize}
    59         print(head_dic)
    60         head_json=json.dumps(head_dic)
    61         head_json_bytes=bytes(head_json,encoding=self.coding)
    62 
    63         head_struct=struct.pack('i',len(head_json_bytes))
    64         self.socket.send(head_struct)
    65         self.socket.send(head_json_bytes)
    66         send_size=0
    67         with open(filename,'rb') as f:
    68             for line in f:
    69                 self.socket.send(line)
    70                 send_size+=len(line)
    71                 print(send_size)
    72             else:
    73                 print('upload successful')
    74 
    75 
    76 
    77 
    78 client=MYTCPClient(('127.0.0.1',8080))
    79 
    80 client.run()
    ftp_client

    三、udp协议套接字多并发                                                             

     1 import socketserver
     2 
     3 class FtpServer(socketserver.BaseRequestHandler):
     4     def handle(self):
     5         print(self.request[0])
     6         print(self.request[1])
     7         self.request[1].sendto('嘎嘎嘎'.encode('utf-8'),self.client_address)
     8 
     9 if __name__ == '__main__':
    10     obj=socketserver.ThreadingUDPServer(('127.0.0.1',8080),FtpServer)
    11     obj.serve_forever()
    server
     1 import socket
     2 
     3 udpclient=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
     4 
     5 server_ip_port=('127.0.0.1',8080)
     6 while True:
     7     inp=input(">>: ")
     8     udpclient.sendto(inp.encode('utf-8'),server_ip_port)
     9 
    10     data,server_addr=udpclient.recvfrom(1024)
    11     print(data.decode('utf-8'))
    client
  • 相关阅读:
    Working with WordprocessingML documents (Open XML SDK)
    How to Choose the Best Way to Pass Multiple Models in ASP.NET MVC
    Azure:Manage anonymous read access to containers and blobs
    Convert HTML to PDF with New Plugin
    location.replace() keeps the history under control
    On the nightmare that is JSON Dates. Plus, JSON.NET and ASP.NET Web API
    HTTP Modules versus ASP.NET MVC Action Filters
    解读ASP.NET 5 & MVC6系列(6):Middleware详解
    Content Negotiation in ASP.NET Web API
    Action Results in Web API 2
  • 原文地址:https://www.cnblogs.com/wangyongsong/p/6813570.html
Copyright © 2011-2022 走看看