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操作MySQL数据库的方法分享
May 29 Python
Python的爬虫包Beautiful Soup中用正则表达式来搜索
Jan 20 Python
Python实现读取并保存文件的类
May 11 Python
python爬虫之urllib3的使用示例
Jul 09 Python
Django开发的简易留言板案例详解
Dec 04 Python
使用python实现语音文件的特征提取方法
Jan 09 Python
Python实现获取系统临时目录及临时文件的方法示例
Jun 26 Python
python3实现二叉树的遍历与递归算法解析(小结)
Jul 03 Python
python字符串反转的四种方法详解
Dec 02 Python
python 串口读取+存储+输出处理实例
Dec 26 Python
python 装饰器功能与用法案例详解
Mar 06 Python
Python3-异步进程回调函数(callback())介绍
May 02 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循环检测目录是否存在并创建(循环创建目录)
2011/01/06 PHP
php去掉文件前几行的方法
2015/07/29 PHP
Yii框架上传图片用法总结
2016/03/28 PHP
Laravel实现通过blade模板引擎渲染视图
2019/10/25 PHP
JavaScript 快捷键设置实现代码
2009/03/13 Javascript
SharePoint 客户端对象模型 (一) ECMA Script
2011/05/22 Javascript
js与运算符和或运算符的妙用
2014/02/14 Javascript
浅析函数声明和函数表达式——函数声明的声明提前
2016/05/03 Javascript
JavaScript中ES6 Babel正确安装过程
2016/07/18 Javascript
利用python分析access日志的方法
2016/10/26 Javascript
jQuery使用JSONP实现跨域获取数据的三种方法详解
2017/05/04 jQuery
vue组件父子间通信详解(三)
2017/11/07 Javascript
js实现鼠标拖拽div左右滑动
2020/01/15 Javascript
vue实现打地鼠小游戏
2020/08/21 Javascript
python连接mongodb操作数据示例(mongodb数据库配置类)
2013/12/31 Python
轻松实现python搭建微信公众平台
2016/02/16 Python
Python paramiko模块的使用示例
2018/04/11 Python
Python os.rename() 重命名目录和文件的示例
2018/10/25 Python
Python关键字及可变参数*args,**kw原理解析
2020/04/04 Python
PyQt5-QDateEdit的简单使用操作
2020/07/12 Python
Python自动发送和收取邮件的方法
2020/08/12 Python
Django与AJAX实现网页动态数据显示的示例代码
2021/02/24 Python
SQL面试题
2013/04/30 面试题
门卫岗位安全职责
2013/12/13 职场文书
教师纪念9.18事件演讲稿范文
2014/09/14 职场文书
党员自我评议个人对照检查材料
2014/09/16 职场文书
房屋出售授权委托书
2014/10/12 职场文书
2014年幼师工作总结
2014/11/22 职场文书
2014年培训工作总结范文
2014/11/27 职场文书
评职称个人总结
2015/03/05 职场文书
2017年寒假社区服务活动总结
2016/04/06 职场文书
幼师必备:幼儿园期末教师评语50条
2019/11/01 职场文书
JS继承最简单的理解方式
2021/03/31 Javascript
如何使用PostgreSQL进行中文全文检索
2021/05/27 PostgreSQL
动态规划之使用备忘录来改进Javascript函数
2022/04/07 Javascript
Java时间工具类Date的常用处理方法
2022/05/25 Java/Android