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 10 Python
python使用socket向客户端发送数据的方法
Apr 29 Python
Python记录详细调用堆栈日志的方法
May 05 Python
Python调用系统底层API播放wav文件的方法
Aug 11 Python
对Python subprocess.Popen子进程管道阻塞详解
Oct 29 Python
Python 获取 datax 执行结果保存到数据库的方法
Jul 11 Python
Django 开发调试工具 Django-debug-toolbar使用详解
Jul 23 Python
python脚本执行CMD命令并返回结果的例子
Aug 14 Python
python实现加密的方式总结
Jan 19 Python
python进行参数传递的方法
May 12 Python
用python写爬虫简单吗
Jul 28 Python
python 监控服务器是否有人远程登录(详细思路+代码)
Dec 18 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
深入了解php4(1)--回到未来
2006/10/09 PHP
discuz7 phpMysql操作类
2009/06/21 PHP
探讨各种PHP字符串函数的总结分析
2013/06/05 PHP
ThinkPHP中关联查询实例
2014/12/02 PHP
php curl常用的5个经典例子
2017/01/20 PHP
php操作access数据库的方法详解
2017/02/22 PHP
javascript+css 网页每次加载不同样式的实现方法
2009/12/27 Javascript
jQuery的Ajax时无响应数据的解决方法
2010/05/25 Javascript
JQuery从头学起第一讲
2010/07/04 Javascript
JS批量操作CSS属性详细解析
2013/12/16 Javascript
JavaScript多图片上传案例
2015/09/28 Javascript
jQuery实现鼠标双击Table单元格变成文本框及输入内容后更新到数据库的方法
2015/11/25 Javascript
js 文字超出长度用省略号代替,鼠标悬停并以悬浮框显示实例
2016/12/06 Javascript
Bootstrap源码解读导航(6)
2016/12/23 Javascript
Canvas 绘制粒子动画背景
2017/02/15 Javascript
js获取ip和地区
2017/03/10 Javascript
详解用node搭建简单的静态资源管理器
2017/08/09 Javascript
在layer弹层layer.prompt中,修改placeholder的实现方法
2019/09/27 Javascript
vue-video-player 解决微信自动全屏播放问题(横竖屏导致样式错乱问题)
2020/02/25 Javascript
利用JavaScript为句子加标题的3种方法示例
2021/01/05 Javascript
[54:57]DOTA2-DPC中国联赛定级赛 Aster vs DLG BO3第二场 1月8日
2021/03/11 DOTA
Python中的文件和目录操作实现代码
2011/03/13 Python
python实现2048小游戏
2015/03/30 Python
Python使用logging结合decorator模式实现优化日志输出的方法
2016/04/16 Python
python实现BackPropagation算法
2017/12/14 Python
详解python实现识别手写MNIST数字集的程序
2018/08/03 Python
Python大数据之网络爬虫的post请求、get请求区别实例分析
2019/11/16 Python
python绘制封闭多边形教程
2020/02/18 Python
解决pycharm导入本地py文件时,模块下方出现红色波浪线的问题
2020/06/01 Python
SQL Server面试题
2013/04/04 面试题
杭州时比特电子有限公司SQL
2013/08/22 面试题
北京申奥口号
2014/06/19 职场文书
百善孝为先:关于孝道的经典语录
2019/10/18 职场文书
python实现web邮箱扫描的示例(附源码)
2021/03/30 Python
python基础入门之字典和集合
2021/06/13 Python
windows11怎么查看wifi密码? win11查看wifi密码的技巧
2021/11/21 数码科技