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 相关文章推荐
在Django的模型和公用函数中使用惰性翻译对象
Jul 27 Python
Python导入模块时遇到的错误分析
Aug 30 Python
Python编程把二叉树打印成多行代码
Jan 04 Python
python主线程捕获子线程的方法
Jun 17 Python
python中plot实现即时数据动态显示方法
Jun 22 Python
python 地图经纬度转换、纠偏的实例代码
Aug 06 Python
搞定这套Python爬虫面试题(面试会so easy)
Apr 03 Python
python求最大值,不使用内置函数的实现方法
Jul 09 Python
pycharm设置python文件模板信息过程图解
Mar 10 Python
Anaconda+VSCode配置tensorflow开发环境的教程详解
Mar 30 Python
Keras中的两种模型:Sequential和Model用法
Jun 27 Python
Python常用配置文件ini、json、yaml读写总结
Jul 09 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获取指定函数定义在哪个文件中以及其所在的行号实例
2014/05/08 PHP
PHP实现时间比较和时间差计算的方法示例
2017/07/24 PHP
jQuery 学习入门篇附实例代码
2010/03/16 Javascript
javascript中方便增删改cookie的一个类
2012/10/11 Javascript
jQuery Validate 验证,校验规则写在控件中的具体实例
2014/02/27 Javascript
Node.js与PHP、Python的字符处理性能对比
2014/07/06 Javascript
jQuery实现带动画效果的二级下拉导航方法
2015/03/11 Javascript
jquery实现页面百叶窗走马灯式翻滚显示效果的方法
2015/03/12 Javascript
JavaScript实现俄罗斯方块游戏过程分析及源码分享
2015/03/23 Javascript
第十章之巨幕页头缩略图与警告框组件
2016/04/25 Javascript
微信小程序 wxapp导航 navigator详解
2016/10/31 Javascript
jQuery插件FusionCharts绘制的3D饼状图效果实例【附demo源码下载】
2017/03/03 Javascript
nodejs模块nodemailer基本使用-邮件发送示例(支持附件)
2017/03/28 NodeJs
超级简易的JS计算器实例讲解(实现加减乘除)
2017/08/08 Javascript
ES6解构赋值的功能与用途实例分析
2017/10/31 Javascript
webpack源码之loader机制详解
2018/04/06 Javascript
详解react内联样式使用webpack将px转rem
2018/09/13 Javascript
详解JavaScript添加给定的标签选项
2018/09/17 Javascript
解决layui中onchange失效以及form动态渲染失效的问题
2019/09/27 Javascript
jquery css实现流程进度条
2020/03/26 jQuery
[47:52]完美世界DOTA2联赛PWL S2 PXG vs InkIce 第二场 11.26
2020/11/30 DOTA
python通过加号运算符操作列表的方法
2015/07/28 Python
Python编程实现输入某年某月某日计算出这一天是该年第几天的方法
2017/04/18 Python
浅谈Pandas 排序之后索引的问题
2018/06/07 Python
python生成九宫格图片
2018/11/19 Python
Pycharm取消py脚本中SQL识别的方法
2018/11/29 Python
Django使用AJAX调用自己写的API接口的方法
2019/03/06 Python
基于python实现查询ip地址来源
2020/06/02 Python
加拿大廉价机票预订网站:CheapOair.ca
2018/03/04 全球购物
加拿大服装和鞋类零售商:Mark’s
2021/01/04 全球购物
致长跑运动员广播稿
2014/01/31 职场文书
会计人员岗位职责
2015/02/03 职场文书
合同审查法律意见书
2015/06/04 职场文书
庆元旦主持词
2015/07/06 职场文书
PHP对接阿里云虚拟号的实现(号码隐私保护)
2021/04/06 PHP
vue中 this.$set的使用详解
2021/11/17 Vue.js