这里总结下一个服务端与多个客户端之间的通信。

先看demo:

#/usr/bin/env python
#_*_coding:utf-8_*_
__author__ = 'ganzl'
import time
import socket
import select
sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sk.bind(('127.0.0.1',6666))
sk.listen(5)
sk.setblocking(False)
inputs = [sk,] #sk就是一个监听的sorcket,放入inputs这个列表中。 while True:
readable_list, writeable_list, error_list = select.select(inputs,[],[],1) #把第一个参数设为列表动态的添加
time.sleep(2)
print "inputs :",inputs #打印inputs列表,查看执行变化
print "readable_list:",readable_list #打印readable_list ,查看执行变化 for r in readable_list:
if r == sk: #sk是一个描述符,
conn,address = r.accept()
inputs.append(conn)#conn是连接socket之后的那根通信管道。
#sk监控的是socket描述符是否有变化,conn监控的是连接后的socket之间两者服务器之间的通信是否有变化
print address
else:
#如果是客户端,接受和返回数据
client_data = r.recv(1024)
if client_data:
r.sendall(client_data)
else:
inputs.remove(r)#如果没有收到客户端端数据,则移除客户端句柄 因为,不管是正常关闭还是异常关闭,client端的系统底层都会发送一个消息
#异常关闭的时候会发送一个空格。
客户端(1)
#!/usr/bin/env python
#_*_coding:utf-8 _*_
__author__ = 'ganzl'
import socket
import time
#创建socket对象
ck = socket.socket()
#通过IP&端口连接server
ck.connect(('127.0.0.1',6666))
#发送消息给服务端
time.sleep(10)
ck.sendall('hello server, this is ganzl---test3---1-')
ck.sendall('hello server, this is ganzl---test3----')
#接收服务端的消息并打印
server_answer = ck.recv(1024)
print server_answer
#关闭连接
ck.close()
客户端(2)

#!/usr/bin/env python
#_*_coding:utf-8 _*_
__author__ = 'ganzl' import socket
ck = socket.socket()
ck.connect(('127.0.0.1',6666))
ck.sendall('hello server, this is ganzl----2----')
server_answer = ck.recv(1024)
print server_answer
ck.close()
客户端(3)

  通过http访问:http://127.0.0.1:6666/

------------------------------------------------------------------------

以上就是用到了IO的多路复用中的select模块。

Python中有一个select模块,其中提供了:select、poll、epoll三个方法,分别调用系统的 select,poll,epoll 从而实现IO多路复用。其他两个方法暂时还没弄懂,空了再看下源码,再百度,再请教其他人。。。

select方法总结:

句柄列表11, 句柄列表22, 句柄列表33 = select.select(句柄序列1, 句柄序列2, 句柄序列3, 超时时间)
 
参数: 可接受四个参数(前三个必须)
返回值:三个列表
 
select方法用来监视文件句柄,如果句柄发生变化,则获取该句柄。
1、当 参数1 序列中的句柄发生可读时(accetp和read),则获取发生变化的句柄并添加到 返回值1 序列中
2、当 参数2 序列中含有句柄时,则将该序列中所有的句柄添加到 返回值2 序列中
3、当 参数3 序列中的句柄发生错误时,则将该发生错误的句柄添加到 返回值3 序列中
4、当 超时时间 未设置,则select会一直阻塞,直到监听的句柄发生变化
   当 超时时间 = 1时,那么如果监听的句柄均无任何变化,则select会阻塞 1 秒,之后返回三个空列表,如果监听的句柄有变化,则直接执行。

写上面这个demo的目的是啥?其实就是SocketServe源码中的最几句核心代码。

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

用一个SocketServer的实际例子来过过代码。方便以后查看,理解。

SocketServer的demo:

服务端:

#!/usr/bin/env python
#_*_coding:utf-8 _*_
__author__ = 'ganzl'
import SocketServer
class MyServer(SocketServer.BaseRequestHandler): def handle(self):
# print self.request,self.client_address,self.server
conn = self.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('请重新输入.')
if __name__ == '__main__':
server = SocketServer.ThreadingTCPServer(('127.0.0.1',8009),MyServer)
server.serve_forever()

客服端:

#!/usr/bin/env python
#_*_coding:utf-8 _*_
__author__ = 'ganzl'
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()

代码实现多个客户端可以同时跟服务器端通信的原因如下:(我自己的类继承了SocketServer.BaseRequestHandler这个类,而它封装了一些基础的类,我自己重写它的方法就好了)

我就不文字描述。 图片就是太难看。有时间再弄个好看的

上图的精简demo如下:

源码精简:(SocketServer)

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 == '':
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()

这里socket用到的都是线程。一个进程中产生的多线程。至于进程线程协程,过段时间搞搞明白。

socket-自我总结(2)的更多相关文章

  1. .net socket 层面实现代理服务器

    socket 层面实现代理服务器 首先是简一个简单的socket客户端和服务器端的例子 建立连接 Socket client = new Socket(AddressFamily.InterNetwo ...

  2. 进程、线程、socket套接字-资源大小 & 切换代价

    另,进程 & 线程的很多知识可以看这里:http://www.cnblogs.com/charlesblc/p/6135666.html 今天查了一下进程和线程的资源占用. 比如问:栈和堆的大 ...

  3. python网络编程socket /socketserver

    提起网络编程,不同于web编程,它主要是C/S架构,也就是服务器.客户端结构的.对于初学者而言,最需要理解的不是网络的概念,而是python对于网络编程都提供了些什么模块和功能.不同于计算机发展的初级 ...

  4. 程序员的自我修养(2)——计算机网络(转) good

    相关文章:程序员的自我修养——操作系统篇 几乎所有的计算机程序,都会牵涉到网络通信.因此,了解计算机基础网络知识,对每一个程序员来说都是异常重要的. 本文在介绍一些基础网络知识的同时,给出了一些高质量 ...

  5. Node+Express+MongoDB + Socket.io搭建实时聊天应用

    Node+Express+MongoDB + Socket.io搭建实时聊天应用 前言 本来开始写博客的时候只是想写一下关于MongoDB的使用总结的,后来觉得还不如干脆写一个node项目实战教程实战 ...

  6. 8.多线程和Socket通信

    一.多线程 1.进程的概念: 进程就是应用程序的执行实例,有独立的内存空间和系统资源.当一个应用程序没有执行的时候,它就不是一个进程.   2.进行的特征: (1)动态性:动态产生动态消亡. (2)并 ...

  7. 浅谈Socket长连+多线程[原创,欢迎指点]

    前戏 [PS:原文手打,转载说明出处] [PS:博主自认为适用于云平台设备管控,且适用于IM主控] 好久没来了,13年时还想着多写一些博客,这都17年过年,年前也写一写Scoket+多线程,不足之处, ...

  8. IO和socket编程

    五一假期结束了,突然想到3周前去上班的路上看到槐花开的正好.放假也没能采些做槐花糕,到下周肯定就老了.一年就开一次的东西,比如牡丹,花期也就一周.而花开之时,玫瑰和月季无法与之相比.明日黄花蝶也愁.想 ...

  9. socket聊天室(服务端)(多线程)(TCP)

    #include<string.h> #include<signal.h> #include<stdio.h> #include<sys/socket.h&g ...

  10. 在c#中利用keep-alive处理socket网络异常断开的方法

    本文摘自 http://www.z6688.com/info/57987-1.htm 最近我负责一个IM项目的开发,服务端和客户端采用TCP协议连接.服务端采用C#开发,客户端采用Delphi开发.在 ...

随机推荐

  1. Python第八天

    Python面向对象进阶 一.静态方法 通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法,什么是静态方法呢?其实不难理解,普通的方法,可以在实例化后直接调用,并且在方法里可以通过 ...

  2. PL/SQL错误提示 database character set(AL32UTF8) and Client character set(ZHS16GBK) are different

    PL/SQL database character set(AL32UTF8) and Client character set(ZHS16GBK) are different 这是由于安装oracl ...

  3. 使用composer管理php项目

    composer global require "fxp/composer-asset-plugin:~1.1.1" composer create-project --prefe ...

  4. zzz

    开放平台(TOP)的API是基于HTTP协议来调用的,开发者(ISV)可以直接使用TOP提供的官方SDK(支持多种语言,包含了请求的封装,签名加密,响应解释,性能优化等)来调用,也可以根据TOP的协议 ...

  5. 反人类的MyEclipse之-Javascript双引号自动补全

    MyEclipse由于在JavaScript中按下一个双引号后会自动把后面的双引号补全.本人习惯两个双引号一起按下,那么这个时候在编辑器里就会出现三个",这样导致代码错误. 今天就因为MyE ...

  6. 转《UNIX编程艺术》读书心得

    花了一段时间看完了<UNIX编程艺术>,但不是看得特别仔细,尤其是后面作者通过对工具的讲解来阐述其设计思想,因为很多工具能未曾接触过,难免就会产生一些乏味的感觉.其实就像译者姜宏在译序里说 ...

  7. JS技术大全(防止复制,粘贴等)

    1. oncontextmenu="window.event.returnValue=false" 将彻底屏蔽鼠标右键 <table border oncontextmenu ...

  8. CuteSTL——跟着感觉造轮子

    置顶推荐: CuteSTL:https://github.com/jxd134/algorithm/tree/master/CuteSTL TinySTL:https://github.com/zou ...

  9. xcode 工具学习笔记

    1. 快速打开辅助界面   快捷键:使用Option + 单击文件   2. 辅助编辑器更多打开方式   快捷键: Option+shift +单击文件   3. tab页面快捷键   快捷键: Co ...

  10. (转)C# 打印PDF文件使用第三方DLL

    本文为转载,原文:http://www.cnblogs.com/Yesi/p/5066835.html DLL地址:https://freepdf.codeplex.com 下面是该解决方案的详细代码 ...