利用select实现伪并发的socket博文中我们说了:

如果要实现一个server端可以和多个客户端进行通信可以使用

1.多线程

2.多进程

3.select I/O多路复用

在那篇博文中我们介绍了使用select模块实现单线程的伪并发的程序间的通信,那今天我们就来谈一谈如何使用多线程来实现并发.

Pyhton本身就提供了一个基于多线程实现并发socket的模块---->SocketServer模块。那么今天我们就来探讨一下SocketSever模块.

SocetServer模块实现并发的原理就是:每有一个客户端连接进来,就会起一个线程负责和这个客户端进行通信。

使用SocketServer模块的时候必须在自定义的类中定义一个handle(方法名必须是handle,差一个字母都不行)方法,在handle方法中去定义具体的操作。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import SocketServer class MyServer(SocketServer.BaseRequestHandler):
def handle(self):
conn = self.request #如果连接请求过来,获取client端对象
conn.sendall('欢迎致电 10086,请输入1xxx,0转人工服务.') #发送一个信息
Flag = True #并把Flag设置为True
while Flag:#当Flag为True的时候执行
data = conn.recv(1024) #接收client端数据
if data == 'exit': #判断如果data == 'exit' 退出
Flag = False #并把Flag设置为Flase
elif data == '': #如果为 == ‘0’
conn.sendall('通过可能会被录音.balabala一大推') #发送数据
else:#上面的都没匹配上,发送请重新输入
conn.sendall('请重新输入.') if __name__ == '__main__':
server = SocketServer.ThreadingTCPServer(('127.0.0.1',8009),MyServer) #实例化对象,设置启动的IP/PORT并把自己定义的类写上作为SocketServer.ThreadingTCPServer的构造函数
server.serve_forever() #调用对象中的启动方法

server

#!/usr/bin/env python
#-*- coding:utf-8 -*- import socket client = socket.socket()
client.connect(('127.0.0.1',8009))
#client.settimeout(5) while True:
client_input = raw_input('please input message:').strip()
client.sendall(client_input)
server_data = client.recv(1024)
print server_data

client

server端的代码实现其实非常简单,但是问题来了:为什么非得让我们定义一个handle方法呢?

  ok,看源码。

学会看源码非常重要!不能仅仅光会用!大赞~ 知道他的过程和实现~ 怎么学会看源码呢?多看然后画类图,如上图!!!

在理解的时候可以把他们想象为,把所有需要用的方法,都抓到ThreadingTCPServer中

内部调用流程为:

  • 启动服务端程序
  • 执行 TCPServer.__init__ 方法,创建服务端Socket对象并绑定 IP 和 端口
  • 执行 BaseServer.__init__ 方法,将自定义的继承自SocketServer.BaseRequestHandler 的类 MyRequestHandle赋值给 self.RequestHandlerClass
  • 执行 BaseServer.server_forever 方法,While 循环一直监听是否有客户端请求到达 ...
  • 当客户端连接到达服务器
  • 执行 ThreadingMixIn.process_request 方法,创建一个 “线程” 用来处理请求
  • 执行 ThreadingMixIn.process_request_thread 方法
  • 执行 BaseServer.finish_request 方法,执行 self.RequestHandlerClass()  即:执行 自定义 MyRequestHandler 的构造方法(自动调用基类BaseRequestHandler的构造方法,在该构造方法中又会调用 MyRequestHandler的handle方法)

精简源码:

模拟Socekt Server的简化版本:

import socket
import threading
import select def process(request, client_address): #模拟定义的handle()方法,这个方法内的代码是socket server与Client端交互代码
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 == '':
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: #这里一个while循环循环监控sk文件句柄
r, w, e = select.select([sk,],[],[],1)
print 'looping'
if sk in r: #当sk文件句柄发生变化的时候说明是新的客户端连接过来了
print 'get request'
request, client_address = sk.accept()
t = threading.Thread(target=process, args=(request, client_address)) #创建一个线程,并调用自己定义的process方法执行~然后样客户端与之交互
t.daemon = False
t.start() sk.close()

精简版

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

参考资料:

http://www.cnblogs.com/luotianshuai/p/5111587.html

SocketServer模块的更多相关文章

  1. socket 和 SocketServer 模块

    一 .Socket 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket socket(TCP,IP)通常也称作"套接字",用于描述IP地址和端 ...

  2. 浅析python中socketserver模块使用

    虽然说用python编写简单的网络程序狠方便,但是复杂一点的网络程序还是用现成的框架比较好,这样就可以专心事物逻辑,而不是套接字的各种细节.Socketserver模块简化了编写网络服务程序,同时so ...

  3. Python网络编程(2)-粘包现象及socketserver模块实现TCP并发

    1. 基于Tcp的远程调用命令实现 很多人应该都使用过Xshell工具,这是一个远程连接工具,通过上面的知识,就可以模拟出Xshell远程连接服务器并调用命令的功能. Tcp服务端代码如下: impo ...

  4. Python之socketserver模块和验证客户端链接的合法性

    验证客户端链接的合法性 分布式系统中实现一个简单的客户端链接认证功能 #_*_coding:utf-8_*_ from socket import * import hmac,os secret_ke ...

  5. python 内置标准库socketserver模块的思考

    socketserver模块简化了编写网络服务器的任务, 在很大程度上封装了一些操作, 你可以看成是事件驱动型的设计, 这很不错.它定义了两个最基本的类--服务器类 BaseServer, 请求处理类 ...

  6. socketserver模块TCP和UDP协议形式

    # >>>>>>>>>>>>>>>>>>>>服务端socketserver模块通 ...

  7. Python网络编程(3)——SocketServer模块与简单并发服务器

    主要类型 该模块有四个比较主要的类,其中常用的是 TCPServer 和 UDPServer. 1. TCPServer 2. UDPServer 3. UnixStreamServer,类似于TCP ...

  8. python-基于UDP通信的套接字,socketserver模块的使用

    一.基于UDP协议通信的套接字 udp是没有链接的,所以先启动哪一端都不会报错 import socket server=socket.socket(socket.AF_INET,socket.SOC ...

  9. udp套接字及利用socketserver模块实现并发以及并发编程

    一:基于udp协议(数据报协议)的套接字:和tcp协议的套接字对比而言,由于udp是无链接的,所以先启动哪一端都不会报错,而且udp也不会有粘包 现象,所以对比下来,tcp协议的话传输数据更加可靠,但 ...

随机推荐

  1. ion-scroll zooming="true" android端无法缩放的问题

    很久很久没更新博客了,从今天开始决定以后陆续写一些博文,总结下自己在开发中碰到的问题. ionic项目.ion-scroll zooming="true" 在android端无法缩 ...

  2. Java中正则表达式去除html标签

    Java中正则表达式去除html的标签,主要目的更精确的显示内容,比如前一段时间在做类似于博客中发布文章功能,当编辑器中输入内容后会将样式标签也传入后台并且保存数据库,但是在显示摘要的时候,比如显示正 ...

  3. TCP/IP协议族(三) 数字签名与HTTPS详解

    前面几篇博客聊了HTTP的相关东西,今天就来聊一聊HTTPS的东西.因为HTTP协议本身存在着明文传输.不能很好的验证通信方的身份和无法验证报文的完整性等一些安全方面的确点,所以才有了HTTPS的缺陷 ...

  4. matlab中hold指令、figure指令及subplot指令的使用

    一.hold指令使用 正常情况下,plot指令显示figure时,以前的数据丢失了.使用hold on指令后,此后添加的一系列plot曲线将叠加在前一个图上当使用hold off后,恢复为默认状况,p ...

  5. 用手机或外部设备在同一局域网下访问虚拟主机wampsever的方法版本号是2.4.9

    1,首先在虚拟服务器电脑上可以打开http://localhost/ 2,在外部设备访问时报错为:You don't have permission to access / in on this se ...

  6. c#访问存储过程

    // 2015/07/04 // 访问存储过程 using System; using System.Collections.Generic; using System.Linq; using Sys ...

  7. GCD(关于容斥原理)

    Problem Description Given 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD( ...

  8. 给ubuntu安装VNC远程桌面

    (只有背景,没有菜单栏问题没有解决)Virtual Network Computing(VNC)是进行远程桌面控制的一个软件.客户端的键盘输入和鼠标操作通过网络传输到远程服务器,控制服务器的操作.服务 ...

  9. Python简单爬虫记录

    为了避免自己忘了Python的爬虫相关知识和流程,下面简单的记录一下爬虫的基本要求和编程问题!! 简单了解了一下,爬虫的方法很多,我简单的使用了已经做好的库requests来获取网页信息和Beauti ...

  10. storm 1.0版本滑动窗口的实现及原理

    滑动窗口在监控和统计应用的场景比较广泛,比如每隔一段时间(10s)统计最近30s的请求量或者异常次数,根据请求或者异常次数采取相应措施.在storm1.0版本之前,没有提供关于滑动窗口的实现,需要开发 ...