Python实现一个服务器监听多个客户端请求


Posted in Python onApril 12, 2018

学习Python网络通信的时候发现书上只有一个服务端对应一个客户端的情形,于是自己想自己动手实现一个服务端响应多个客户端。

首先建立服务器的socket来监听客户端的请求:

tcpSerSock=socket(AF_INET,SOCK_STREAM) 
tcpSerSock.bind(ADDR) 
tcpSerSock.listen(5)

这样服务器的监听socket就建好了。

接下来的思路是,如果要监听多个客户端,则

tcpSerSock.accept() #(accept()是阻塞式的)

必须放进一个while循环(不放进循环监听一次就没了)。然而,这里就有问题了。如果按照一对一的那种处理顺序,客户端A连进来后,程序顺序向下执行,服务端要再写一个while循环,用来处理客户端A的请求,如果此时客户端B再来请求,服务器将接收不到。于是,很自然想到,将监听和处理放到不同的线程进行处理。我选择将监听放入主线程,将处理放进子线程。该服务器功能为接收到客户端的数据加上时间戳后返回给客户端。服务端完整代码如下:

#coding=utf-8 
#!/usr/bin/env python 
''''' 
author:Mr.Jing 
created on Fri Sep 22 14:29:03 2017 
platfrom:win10,python2.7 
''' 
 
from socket import * 
from time import ctime 
import threading 
import time 
HOST='' 
PORT=2159 
BUFSIZ=1024 
ADDR = (HOST,PORT) 
 
tcpSerSock=socket(AF_INET,SOCK_STREAM) 
tcpSerSock.bind(ADDR) 
tcpSerSock.listen(5) 
socks=[]        #放每个客户端的socket 
 
def handle(): 
 while True: 
  for s in socks: 
   data = s.recv(BUFSIZ) 
   if not data: 
    socks.remove(s) 
    continue 
   s.send('[%s],%s' % (ctime(), data)) #加上时间戳返回 
 
t = threading.Thread(target=handle)    #子线程 
if __name__ == '__main__': 
 t.start() 
 print u'我在%s线程中 ' % threading.current_thread().name #本身是主线程 
 print 'waiting for connecting...' 
 while True: 
  clientSock,addr = tcpSerSock.accept() 
  print 'connected from:', addr 
  socks.append(clientSock)

两个客户端A和B同时连接,服务器输出:

Python实现一个服务器监听多个客户端请求

可以看到服务端是可以相应多个客户端的。

客户端A发条消息试试?

Python实现一个服务器监听多个客户端请求

服务器返回来了带时间戳的消息,goodjob。

那另一个呢?

Python实现一个服务器监听多个客户端请求

很棒。服务器都能做出响应。

再发一条试试?

Python实现一个服务器监听多个客户端请求

发现服务器没响应了,这是怎么回事呢?

经过仔细勘察发现是因为这句:

data = s.recv(BUFSIZ)

因为recv方法是阻塞的,也就是说,当轮训到某个客户端,比如A,这句等待A发消息,不发消息就不往下走,所以此时B再去发消息的话服务器就收不到了。

那该怎么办呢?

很容易想到,将其设为非阻塞就好了。但上网找了好久,虽然找到可以用setblocking(0)  将套接字设为非阻塞,然而具体怎么用却很少有人讲清楚。查资料后终于搞明白,非阻塞的recv方法会继续向下执行,若超时得不到数据则会抛出异常。

修改后的代码如下:

#coding=utf-8 
#!/usr/bin/env python 
''''' 
author:Mr.Jing 
created on Fri Sep 22 14:29:03 2017 
platfrom:win10,python2.7 
''' 
 
from socket import * 
from time import ctime 
import threading 
import time 
HOST='' 
PORT=2159 
BUFSIZ=1024 
ADDR = (HOST,PORT) 
 
tcpSerSock=socket(AF_INET,SOCK_STREAM) 
tcpSerSock.bind(ADDR) 
tcpSerSock.listen(5) 
socks=[]        #放每个客户端的socket 
 
def handle(): 
 while True: 
  for s in socks: 
   try: 
    data = s.recv(BUFSIZ)  #到这里程序继续向下执行 
   except Exception, e:   
    continue 
   if not data: 
    socks.remove(s) 
    continue 
   s.send('[%s],%s' % (ctime(), data)) 
 
t = threading.Thread(target=handle)    #子线程 
if __name__ == '__main__': 
 t.start() 
 print u'我在%s线程中 ' % threading.current_thread().name #本身是主线程 
 print 'waiting for connecting...' 
 while True: 
  clientSock,addr = tcpSerSock.accept() 
  print 'connected from:', addr 
  clientSock.setblocking(0) 
  socks.append(clientSock)

此时再去尝试:

Python实现一个服务器监听多个客户端请求

客户端随便输都会得到响应。任务达成!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python xlrd读取excel日期类型的2种方法
Apr 28 Python
python嵌套函数使用外部函数变量的方法(Python2和Python3)
Jan 31 Python
简单谈谈python中的语句和语法
Aug 10 Python
Atom的python插件和常用插件说明
Jul 08 Python
python 读取视频,处理后,实时计算帧数fps的方法
Jul 10 Python
python爬虫-模拟微博登录功能
Sep 12 Python
python Dijkstra算法实现最短路径问题的方法
Sep 19 Python
Django框架model模型对象验证实现方法分析
Oct 02 Python
使用IDLE的Python shell窗口实例详解
Nov 19 Python
python交互模式基础知识点学习
Jun 18 Python
Pycharm无法打开双击没反应的问题及解决方案
Aug 17 Python
Python通过m3u8文件下载合并ts视频的操作
Apr 16 Python
python使用socket创建tcp服务器和客户端
Apr 12 #Python
Python简单实现两个任意字符串乘积的方法示例
Apr 12 #Python
Java与Python两大幸存者谁更胜一筹呢
Apr 12 #Python
python打包压缩、读取指定目录下的指定类型文件
Apr 12 #Python
pandas全表查询定位某个值所在行列的方法
Apr 12 #Python
Python Pandas找到缺失值的位置方法
Apr 12 #Python
Pandas 数据框增、删、改、查、去重、抽样基本操作方法
Apr 12 #Python
You might like
用PHP实现的生成静态HTML速度快类库
2007/03/31 PHP
ecshop后台编辑器替换成ueditor编辑器
2015/03/03 PHP
php根据数据id自动生成编号的实现方法
2016/10/16 PHP
jQuery 添加/移除CSS类实现代码
2010/02/11 Javascript
JQuery之拖拽插件实现代码
2011/04/14 Javascript
Extjs TimeField 显示正常时间格式的代码
2011/06/28 Javascript
jQuery学习笔记之Ajax用法实例详解
2015/12/01 Javascript
使用angularjs创建简单表格
2016/01/21 Javascript
JavaScript实现身份证验证代码
2016/02/17 Javascript
jQuery侧边栏实现代码
2016/05/06 Javascript
深入理解JavaScript内置函数
2016/06/03 Javascript
jQuery基本筛选选择器实例代码
2017/02/06 Javascript
Vue精简版风格概述
2018/01/30 Javascript
jquery 回调操作实例分析【回调成功与回调失败的情况】
2019/09/27 jQuery
Weex开发之WEEX-EROS开发踩坑(小结)
2019/10/16 Javascript
关于vue.js中实现方法内某些代码延时执行
2019/11/14 Javascript
[02:50]【扭转乾坤,只此一招】DOTA2全新版本永雾林渊开启新篇章
2020/12/24 DOTA
[06:45]DOTA2-DPC中国联赛 正赛 Magma vs LBZS 选手采访
2021/03/11 DOTA
Python 中的 else详解
2016/04/23 Python
完美解决Python2操作中文名文件乱码的问题
2017/01/04 Python
python数据处理实战(必看篇)
2017/06/11 Python
Python2与Python3的区别实例总结
2019/04/17 Python
Python从文件中读取指定的行以及在文件指定位置写入
2019/09/06 Python
浅谈python3打包与拆包在函数的应用详解
2020/05/02 Python
python zip()函数的使用示例
2020/09/23 Python
PyChon中关于Jekins的详细安装(推荐)
2020/12/28 Python
Jupyter Notebook 远程访问配置详解
2021/01/11 Python
python中用ggplot绘制画图实例讲解
2021/01/26 Python
纯CSS3单页切换导航菜单界面设计的简单实现
2016/08/16 HTML / CSS
HTML5的一个显示电池状态的API简介
2015/06/18 HTML / CSS
什么是命名空间(NameSpace)
2015/11/24 面试题
医学护理毕业生自荐信
2013/11/07 职场文书
班长岗位职责
2013/11/10 职场文书
如何写一份好的自荐信
2014/01/02 职场文书
三月学雷锋月活动总结
2014/04/28 职场文书
pytest实现多进程与多线程运行超好用的插件
2022/07/15 Python