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通过smpt发送邮件的方法
Apr 30 Python
pandas将numpy数组写入到csv的实例
Jul 04 Python
Tensorflow 合并通道及加载子模型的方法
Jul 26 Python
python实现给scatter设置颜色渐变条colorbar的方法
Dec 13 Python
Python实现批量执行同目录下的py文件方法
Jan 11 Python
python爬取微信公众号文章的方法
Feb 26 Python
Django项目中添加ldap登陆认证功能的实现
Apr 04 Python
基于django channel实现websocket的聊天室的方法示例
Apr 11 Python
详解【python】str与json类型转换
Apr 29 Python
基于MSELoss()与CrossEntropyLoss()的区别详解
Jan 02 Python
pytorch实现查看当前学习率
Jun 24 Python
Python数据分析之绘图和可视化详解
Jun 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
SSI指令
2006/11/25 PHP
php下实现折线图效果的代码
2007/04/28 PHP
PHP里的单例类写法实例
2015/06/25 PHP
PHP常用函数总结(180多个)
2016/12/25 PHP
Node.js实现简单聊天服务器
2014/06/20 Javascript
分享一款基于jQuery的视频播放插件
2014/10/09 Javascript
javascript修改图片src的方法
2015/01/27 Javascript
使用jQuery实现WordPress中的Ctrl+Enter和@评论回复
2016/05/21 Javascript
jquery平滑滚动到顶部插件使用详解
2017/05/08 jQuery
使用vue打包时vendor文件过大或者是app.js文件很大的问题
2018/06/29 Javascript
nodejs实现获取本地文件夹下图片信息功能示例
2019/06/22 NodeJs
vue proxy 的优势与使用场景实现
2020/06/15 Javascript
八种Vue组件间通讯方式合集(推荐)
2020/08/18 Javascript
[30:55]完美世界DOTA2联赛PWL S2 Magma vs LBZS 第二场 11.18
2020/11/18 DOTA
Python中的闭包总结
2014/09/18 Python
Python 自动补全(vim)
2014/11/30 Python
Python使用metaclass实现Singleton模式的方法
2015/05/05 Python
Numpy中stack(),hstack(),vstack()函数用法介绍及实例
2018/01/09 Python
Numpy数组转置的两种实现方法
2018/04/17 Python
详解Python安装scrapy的正确姿势
2018/06/26 Python
使用Django和Postgres进行全文搜索的实例代码
2020/02/13 Python
基于python的docx模块处理word和WPS的docx格式文件方式
2020/02/13 Python
Python动态导入模块和反射机制详解
2020/02/18 Python
Python3-异步进程回调函数(callback())介绍
2020/05/02 Python
使用pytorch实现论文中的unet网络
2020/06/24 Python
python脚本和网页有何区别
2020/07/02 Python
python实现数字炸弹游戏
2020/07/17 Python
如何在 Matplotlib 中更改绘图背景的实现
2020/11/26 Python
详解python定时简单爬取网页新闻存入数据库并发送邮件
2020/11/27 Python
New Balance法国官方网站:购买鞋子和服装
2019/09/01 全球购物
施工协议书范本
2014/04/22 职场文书
离婚律师函范本
2015/05/27 职场文书
5分钟教你docker安装启动redis全教程(全新方式)
2021/05/29 Redis
为什么在foreach循环中JAVA集合不能添加或删除元素
2021/06/11 Java/Android
go开发alertmanger实现钉钉报警
2021/07/16 Golang
CentOS8.4安装Redis6.2.6的详细过程
2021/11/20 Redis