SocketServer模块

基本概念

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

原理

1、服务器启动socket监听端口

2、服务器内部利用while循环监视句柄的变化

3、客户端请求

4、服务器为这个请求分配线程或进程(底层调用select)。

SocketServer模块有两个方法ThreadingTCPServer和ForkingTCPServer,分别创建线程或者进程。

ThreadingTCPServer

定义

ThreadingTCPServer实现的Soket服务器内部会为每个client创建一个 “线程”,该线程用来和客户端进行交互。

使用方法:

1、创建一个继承自 SocketServer.BaseRequestHandler 的类

2、类中必须定义一个名称为 handle 的方法(名称不能更改)

3、启动ThreadingTCPServer

server代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

#!/usr/bin/env python

# -*- coding:utf-8 -*-

import SocketServer

class MyServer(SocketServer.BaseRequestHandler):

    def handle(self):       #函数名必须是handle,源码BaseRequestHandler预定义;

        print self.request,self.client_address,self.server  #BaseRequestHandler的__init__定义好的;

        conn = self.request     #每个连接的socket

        conn.sendall(‘欢迎致电 10086,请输入1xxx,0转人工服务.‘)

        Flag = True

        while Flag:

            data = conn.recv(1024)

            if data == ‘exit‘:

                Flag = False

            elif data == ‘0‘:

                conn.sendall(‘通话可能会被录音.balabala一大推‘)

            else:

                conn.sendall(‘请重新输入.‘)

if __name__ == ‘__main__‘:

    server = SocketServer.ThreadingTCPServer((‘127.0.0.1‘,8009),MyServer)   #实例化ThreadingTCPServer,其实是继承TCPServer类的初始化,需要传入(server_address, RequestHandlerClass),RequestHandlerClass就是MyServer类。

    server.serve_forever()  #启动服务,用select一直在循环执行,继承自BaseServer类的方法serve_forever();

client代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

#!/usr/bin/env python

# -*- coding:utf-8 -*-

import socket

ip_port = (‘127.0.0.1‘,8009)

sk = socket.socket()

sk.connect(ip_port)

sk.settimeout(5)

while True:

    data = sk.recv(1024)

    print ‘receive:‘,data

    inp = raw_input(‘please input:‘)

    sk.sendall(inp)

    if inp == ‘exit‘:

        break

sk.close()

ForkingTCPServer

ThreadingTCPServer实现的Soket服务器内部会为每个client创建一个 “进程”,该线程用来和客户端进行交互。

ForkingTCPServer和ThreadingTCPServer的使用和执行流程基本一致,只不过在内部分别为请求者建立 “线程”  和 “进程”。

server代码不同处:

  1. server = SocketServer.ThreadingTCPServer((‘127.0.0.1‘,8009),MyRequestHandler)
  2. 变更为:
  3. server = SocketServer.ForkingTCPServer((‘127.0.0.1‘,8009),MyRequestHandler)

ThreadingTCPServer源码分析(ForkingTCPServer方法类似

类继承关系图

服务器启动程序后:

1、执行 TCPServer.__init__ 方法,创建服务端Socket对象并绑定 IP 和 端口

解释:class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass,ThreadingTCPServer先要执行__init__构造函数,ThreadingMixIn里没有,就去TCPServer类里去找

2、执行 BaseServer.__init__ 方法,将自定义的继承自SocketServer.BaseRequestHandler 的类 MyRequestHandle赋值给self.RequestHandlerClass

解释:TCPServer构造方法中包含BaseServer.__init__(self, server_address, RequestHandlerClass),所以要把自己定义的类传给BaseServer的构造方法

3、执行 BaseServer.server_forever 方法,While 循环一直监听是否有客户端请求到达 ...

解释:serve_forever是BaseServer类中的方法,里面有个while循环,一直调用select.select(),r, w, e = _eintr_retry(select.select, [self], [], [],poll_interval)

客户端接入:

4、执行BaseServer._handle_request_noblock方法

解释:serve_forever的while循环里有一个判断if self in r:self._handle_request_noblock(),客户端连接句柄发生变化就会把句柄放到r列表里,所以,触发了_handle_request_noblock()。

5、执行 ThreadingMixIn.process_request 方法,创建一个 “线程” 用来处理请求

解释:调用process_request方法时,从继承类广度优先原则,所以它先调用ThreadingMixIn类中的process_request

6、执行 ThreadingMixIn.process_request_thread 方法

解释:t = threading.Thread(target = self.process_request_thread,args = (request, client_address))多线程模块方法,调用self.process_request_thread,此时才真正启动了线程。

7、执行 BaseServer.finish_request 方法,执行 self.RequestHandlerClass()  即:执行 自定义 MyRequestHandler 的构造方法(自动调用基类BaseRequestHandler的构造方法,在该构造方法中又会调用自定义的MyRequestHandler的handle方法)

解释:连接创建完成,此时开始执行handle方法中的内容,开始和客户端交互,执行完,后面再执行shutdown_request方法关闭连接。

源码精简


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

import socket

import threading

import select

def process(request, client_address):

    print request,client_address

    conn = request

    conn.sendall(‘欢迎致电 10086,请输入1xxx,0转人工服务.‘)

    flag = True

    while flag:

        data = conn.recv(1024)

        if data == ‘exit‘:

            flag = False

        elif data == ‘0‘:

            conn.sendall(‘通过可能会被录音.balabala一大推‘)

        else:

            conn.sendall(‘请重新输入.‘)

sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

sk.bind((‘127.0.0.1‘,8002))

sk.listen(5)

while True:

    r, w, e = select.select([sk,],[],[],1)

    print ‘looping‘

    if sk in r:

        print ‘get request‘

        request, client_address = sk.accept()

        t = threading.Thread(target=process, args=(request, client_address))

        t.daemon = False

        t.start()

sk.close()

如精简代码可以看出,SocketServer的ThreadingTCPServer之所以可以同时处理请求得益于 select 和 Threading 两个东西,其实本质上就是在服务器端为每一个客户端创建一个线程,当前线程用来处理对应客户端的请求,所以,可以支持同时n个客户端链接(长连接)。

来源: http://www.cnblogs.com/wupeiqi/articles/5040823.html

来自为知笔记(Wiz)

时间: 2024-11-06 15:19:22

SocketServer模块的相关文章

数据库:socketserver模块、MySQL(一)

一.socketserver实现并发 基于tcp的套接字,关键就是两个循环,一个链接循环,一个通信循环. socketserver模块中分两大类:server类(解决链接问题)和request类(解决通信问题) server类: request类: 继承关系: 以下述代码为例,分析socketserver源码: ftpserver=socketserver.ThreadingTCPServer(('127.0.0.1',8080),FtpServer)ftpserver.serve_foreve

python小白-day8 socketserver模块

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

并发编程之socketserver模块

一.socketserver模块介绍 基于tcp套接字,关键的就是两个循环,一个是链接循环,一个是通信循环 socketserver模块中分两大类:srever类(解决链接问题)和request类(解决通信问题) 源码分析总结: 基于tcp的socketserver我们自己定义的类中 1.    self.server即套接字对象 2.    self.request即一个链接 3.    self.client_address即客户端地址 基于udp的socketserver我们自己定义的类中

Day43:socketserver模块、MySQL

一.socketserver实现并发 基于tcp的套接字,关键就是两个循环,一个链接循环,一个通信循环. socketserver模块中分两大类:server类(解决链接问题)和request类(解决通信问题) server类: request类: 继承关系: 以下述代码为例,分析socketserver源码: ftpserver=socketserver.ThreadingTCPServer(('127.0.0.1',8080),FtpServer)ftpserver.serve_foreve

socket 和 SocketServer 模块

一 .Socket 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket socket(TCP,IP)通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求 socket和file的区别: file模块是针对某个指定文件进行[打开][读写][关闭] socket模块是针对 服务器端 和 客户端Socket 进行[打开][读写][关闭] 建立连接必须有一个服务端和一

SocketServer 模块

SocketServer 模块是一个基于 socket 模块的高级别的套接字通讯模块,用于简化网络客户与服务器的实现,它支持使用多进程或多线程处理客户端请求 [[email protected] ~]# cat socketserver.py #!/usr/bin/env python #-*- coding:utf-8 -*- import SocketServer class MyTCPHandler(SocketServer.BaseRequestHandler): # 定义一个类,并继承

Python全栈开发--socketserver模块和验证客户端链接的合法性

验证客户端链接的合法性 分布式系统中实现一个简单的客户端链接认证功能 #_*_coding:utf-8_*_ from socket import * import hmac,os secret_key=b'linhaifeng bang bang bang' def conn_auth(conn): ''' 认证客户端链接 :param conn: :return: ''' print('开始验证新链接的合法性') msg=os.urandom(32) conn.sendall(msg) h=

33、验证客户端的合法性、socketserver模块

一.为了防止客户端被人非法利用,需要在使用之前对客户端进行合法性验证.接下来就是客户端验证的几种方法 hmac  加密方法 以下是服务端: import socket import os import hmac #能转化成密文模块 secret_key=b'apple' #密钥,必须是bytes类型 sk=socket.socket() sk.bind(('127.0.0.1',8008)) sk.listen() def check_con(con): #定义一个验证函数 msg=os.ura

Python学习——socketserver模块

socketserver模块就是socket模块的封装. The socketserver module simplifies the task of writing network servers. socketserver一共有这么几种类型 1 class socketserver.TCPServer(server_address, RequestHandlerClass, bind_and_activate=True) This uses the Internet TCP protocol