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当中的字符串和编码
Apr 25 Python
图文详解WinPE下安装Python
May 17 Python
Python自动化开发学习之三级菜单制作
Jul 14 Python
python处理Excel xlrd的简单使用
Sep 12 Python
Python3.6笔记之将程序运行结果输出到文件的方法
Apr 22 Python
python cs架构实现简单文件传输
Mar 20 Python
Win10下python3.5和python2.7环境变量配置教程
Sep 18 Python
对python中UDP,socket的使用详解
Aug 22 Python
手机使用python操作图片文件(pydroid3)过程详解
Sep 25 Python
Python利用PyPDF2库获取PDF文件总页码实例
Apr 03 Python
Django {{ MEDIA_URL }}无法显示图片的解决方式
Apr 07 Python
python实现单机五子棋
Aug 28 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维护文件系统
2006/10/09 PHP
php中解析带中文字符的url函数分享
2015/01/20 PHP
Laravel (Lumen) 解决JWT-Auth刷新token的问题
2019/10/24 PHP
DB.ASP 用Javascript写ASP很灵活很好用很easy
2011/07/31 Javascript
JS记录用户登录次数实现代码
2014/01/15 Javascript
JavaScript对Cookie进行读写操作实例
2015/07/25 Javascript
微信小程序 教程之wxapp视图容器 swiper
2016/10/19 Javascript
用iframe实现不刷新整个页面上传图片的实例
2016/11/18 Javascript
jQuery为DOM动态追加事件的方法
2017/02/16 Javascript
JavaScript实现QQ聊天消息展示和评论提交功能
2017/05/22 Javascript
解决vuejs项目里css引用背景图片不能显示的问题
2018/09/13 Javascript
js回文数的4种判断方法示例
2019/06/04 Javascript
angularjs1.X 重构controller 的方法小结
2019/08/15 Javascript
vue 自定义右键样式的实例代码
2019/11/06 Javascript
[54:18]DOTA2-DPC中国联赛 正赛 PSG.LGD vs LBZS BO3 第一场 1月22日
2021/03/11 DOTA
Python操作json数据的一个简单例子
2014/04/17 Python
利用Python如何实现一个小说网站雏形
2018/11/23 Python
Django之提交表单与前后端交互的方法
2019/07/19 Python
python 环境搭建 及python-3.4.4的下载和安装过程
2019/07/20 Python
Django实现web端tailf日志文件功能及实例详解
2019/07/28 Python
Tensorflow中的降维函数tf.reduce_*使用总结
2020/04/20 Python
浅析Python __name__ 是什么
2020/07/07 Python
python实现定时发送邮件到指定邮箱
2020/12/23 Python
美国女性卫生用品公司:Thinx
2017/06/30 全球购物
全球最大最受欢迎的旅游社区:Tripadvisor
2017/11/03 全球购物
波兰在线运动商店:YesSport
2020/07/23 全球购物
小学生中国梦演讲稿
2014/04/23 职场文书
文明之星事迹材料
2014/05/09 职场文书
驾驶员安全责任书范本
2014/07/24 职场文书
爱国影片观后感
2015/06/18 职场文书
数学备课组工作总结
2015/08/12 职场文书
建议书的格式及范文
2015/09/14 职场文书
2016年“11.11”光棍节活动总结
2016/04/05 职场文书
详解Laravel制作API接口
2021/05/31 PHP
MySQL的Query Cache图文详解
2021/07/01 MySQL
解决使用了nginx获取IP地址都是127.0.0.1 的问题
2021/09/25 Servers