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 相关文章推荐
Python3处理文件中每个词的方法
May 22 Python
Python实现文件复制删除
Apr 19 Python
听歌识曲--用python实现一个音乐检索器的功能
Nov 15 Python
python 爬虫 批量获取代理ip的实例代码
May 22 Python
pymongo中group by的操作方法教程
Mar 22 Python
深入解析Python小白学习【操作列表】
Mar 23 Python
python做反被爬保护的方法
Jul 01 Python
Python常用模块sys,os,time,random功能与用法实例分析
Jan 07 Python
解决django中form表单设置action后无法回到原页面的问题
Mar 13 Python
Django创建一个后台的基本步骤记录
Oct 02 Python
pycharm Tab键设置成4个空格的操作
Feb 26 Python
Python加密与解密模块hashlib与hmac
Jun 05 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中常用编辑器推荐
2007/01/02 PHP
PHP 上传文件大小限制
2009/07/05 PHP
php数据结构与算法(PHP描述) 快速排序 quick sort
2012/06/21 PHP
如何使用PHP获取指定日期所在月的开始日期与结束日期
2013/08/01 PHP
基于preg_match_all采集后数据处理的一点心得笔记(编码转换和正则匹配)
2014/01/31 PHP
php采集内容中带有图片地址的远程图片并保存的方法
2015/01/03 PHP
微信公众号实现会员卡领取功能
2017/06/08 PHP
PHP定义字符串的四种方式详解
2018/02/06 PHP
使用Jquery Aajx访问WCF服务(GET、POST、PUT、DELETE)
2012/03/16 Javascript
浅谈Javascript事件处理程序的几种方式
2012/06/27 Javascript
js中生成map对象的方法
2014/01/09 Javascript
把字符串按照特定的字母顺序进行排序的js代码
2014/01/28 Javascript
javascript的解析执行顺序在各个浏览器中的不同
2014/03/17 Javascript
jquery实现兼容IE8的异步上传文件
2015/06/15 Javascript
JS拖拽插件实现步骤
2015/08/03 Javascript
javascript点击按钮实现隐藏显示切换效果
2016/02/03 Javascript
微信开发 使用picker封装省市区三级联动模板
2016/10/28 Javascript
ionic中列表项增加和删除的实现方法
2017/01/22 Javascript
Vue2 Vue-cli中使用Typescript的配置详解
2017/07/24 Javascript
vue页面使用阿里oss上传功能的实例(二)
2017/08/09 Javascript
VueJs 搭建Axios接口请求工具
2017/11/20 Javascript
JS实现调用本地摄像头功能示例
2018/05/18 Javascript
在vue项目中优雅的使用SVG的方法实例详解
2018/12/03 Javascript
async/await让异步操作同步执行的方法详解
2019/11/01 Javascript
js布局实现单选按钮控件
2020/01/17 Javascript
jQuery实现中奖播报功能(让文本滚动起来) 简单设置数值即可
2020/03/20 jQuery
[48:44]2014 DOTA2国际邀请赛中国区预选赛5.21 TongFu VS HGT
2014/05/22 DOTA
Python中的字符串查找操作方法总结
2016/06/27 Python
python常见的格式化输出小结
2016/12/15 Python
用生成器来改写直接返回列表的函数方法
2017/05/25 Python
Python logging模块进行封装实现原理解析
2020/08/07 Python
职业教育毕业生求职信
2013/11/09 职场文书
公司大门门卫岗位职责
2014/06/11 职场文书
医院护士党的群众路线教育实践活动对照检查材料思想汇报
2014/10/04 职场文书
简历自我评价模板
2015/03/11 职场文书
redis客户端实现高可用读写分离的方式详解
2021/07/04 Redis