python并发request_10.python网络编程(socket server 实现并发 part 2)

一、基于tcp的socket通信的基本原理分析。

基于tcp的socket通信,主要依靠两个循环,分别是连接循环和通信循环。

这个前面的文章有写过,在这里就不再重复了。

二、socketserver实现多并发的原理分析。

1.server类:

1036857-20170505014200961-1776184607.png

2.reques类。

1036857-20170505014309914-771361140.png

类继承关系:

1036857-20170505015158101-334152905.png

1036857-20170505015356492-1711228984.png

示例代码:import socketserver

import struct

import json

import os

class FtpServer(socketserver.BaseRequestHandler):

coding='utf-8'

server_dir='file_upload'

max_packet_size=1024

BASE_DIR=os.path.dirname(os.path.abspath(__file__))

def handle(self):

print(self.request)

while True:

data=self.request.recv(4)

data_len=struct.unpack('i',data)[0]

head_json=self.request.recv(data_len).decode(self.coding)

head_dic=json.loads(head_json)

# print(head_dic)

cmd=head_dic['cmd']

if hasattr(self,cmd):

func=getattr(self,cmd)

func(head_dic)

def put(self,args):

file_path = os.path.normpath(os.path.join(

self.BASE_DIR,

self.server_dir,

args['filename']

))

filesize = args['filesize']

recv_size = 0

print('----->', file_path)

with open(file_path, 'wb') as f:

while recv_size 

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))

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

ftpserver.serve_forever()

分析开始:

结合上面的例子,还有类关系图一块看。ftpserver=socketserver.ThreadingTCPServer(('127.0.0.1',8080),FtpServer)

ftpserver.serve_forever()

查找属性的顺序:ThreadingTCPServer->ThreadingMixIn->TCPServer->BaseServer通过ThreadingTCPServer 这个类,实例化出一个ftpserver对象。

1.2 先从ThreadingTCPServer这个类中找__init__方法,SocketServer的源码中可以看到,它本身并没有__init__方法,这时候就从ThreadingTCPServer所继承的两个父类中去找。从源码中可以看到ThreadingTCPServer一共继承了两个父类,分别是ThreadingMixIn和TCPServer,其中ThreadingMixIn中也没有__init__方法,最终在TCPServer下找到了__init__,此时执行TCPServer下的__init__方法。

1.3 TCPServer下的__init__方法一共做了四件事,分别是执行了BaseServer类下的__init__方法,创                                    建了socket对象,绑定了IP地址和端口(bind),以及开始listen监听。

BaseServer类下的__init__方法,做了两件事,为创建出来的对象添加了两个属性,分别                                            是server_address和RequestHandlerClass,其中server_address是服务端绑定的ip地址和端                        口,RequestHandlerClass是前面我们自己创建的FtpServer类。

(完成了bind和listen操作是因为执行了server_bind和server_active)

2.Serve_forever 实现连接循环。

2.1前面说了,ftpserver这个对象是由ThreadingTCPServer这个类创建出来的,所以说,默认情况下ftpserver这个对象本身,以及ThreadingTCPServer这个类都没有Serve_forever这个方法,依旧按照上面的套路,阅读源码,从ThreadingTCPServer继承的父类中去找,分别是ThreadingMixIn和TCPServer,在这两个父类中都没有找到,接着去看ThreadingMixIn和TCPServer继承的父类....关于继承顺序的概念在这也不再赘述.....最终在BaseServer中找到了Serve_forever这个方法。

2.2serve_forever下主要执行self._handle_request_noblock()进而执行request, client_address = self.get_request()(就是TCPServer中的self.socket.accept()),然后执行self.process_request(request, client_address)

在ThreadingMixIn中找到process_request,开启多线程应对并发,进而执行process_request_thread,执行self.finish_request(request, client_address)。

2.3上述四部分完成了链接循环,本部分开始进入处理通讯部分,在BaseServer中找到finish_request,触发我们自己定义的类的实例化,去找__init__方法,而我们自己定义的类没有该方法,则去它的父类也就是BaseRequestHandler中找....

最后总结下创建socketserver的几个步骤。First, you must create a request handler class by subclassing the BaseRequestHandlerclass and overriding its handle() method; this method will process incoming requests.

首先你必须创建一个类,这个类必须是BaseRequestHandler的子类,并且这个类必须要有一个handle方法,这个方法用来处理连接进来的请求。

2.Second, you must instantiate one of the server classes, passing it the server’s address and the request handler class.

其次你必须实例化一个服务器类,在实例化的过程中,需要传入服务端地址 以及 那个请求句柄的类。

3.Then call the handle_request() or serve_forever() method of the server object to process one or many requests.

然后,执行服务器对象的handle_request()或 serve_forever()方法 ,来处理一个或多个请求。

4.Finally, call server_close() to close the socket.

最后,执行server_close()这个方法关闭套接字。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值