python实现socket+threading处理多连接的方法


Posted in Python onJuly 23, 2019

一.运行效果

先说两句,之前我在网上找的相关文章标题上写的是处理多连接,尼玛,全是假的。网上那些,根本不能异步处理多连接,不能主动给客户端发消息。

python实现socket+threading处理多连接的方法

在服务端控制台输入1,查看在线人数。

python实现socket+threading处理多连接的方法

给指定客户端发送消息。

python实现socket+threading处理多连接的方法

二.开发思路

以下说的是服务端开发思路,客户端比较简单就不说了。

首先,需要明白的是socket的accept和recv这两个方法是阻塞线程的。这就意味着我们需要新开线程来处理这两个方法。

具体的程序流程大概是这样的:

1.新开一个线程用于接收新的连接(socket.accept())

2.当有新的连接时,再新开一个线程,用于接收这个连接的消息(socket.recv())

3.主线程做为控制台,接收用户的输入,进行其他操作

也就是说,服务端需要为每一个连接创建一个线程。

三.服务端代码

全局部分的代码:

import socket # 导入 socket 模块
from threading import Thread
 
ADDRESS = ('127.0.0.1', 8712) # 绑定地址
 
g_socket_server = None # 负责监听的socket
 
g_conn_pool = [] # 连接池

其中,g_conn_pool是用来存放每一个客户端socket的。

初始化服务端:

def init():
  """
  初始化服务端
  """
  global g_socket_server
  g_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建 socket 对象
  g_socket_server.bind(ADDRESS)
  g_socket_server.listen(5) # 最大等待数(有很多人理解为最大连接数,其实是错误的)
  print("服务端已启动,等待客户端连接...")

socket.listen()的参数意义不要理解错了哦~

接收客户端连接和处理客户端消息:

def accept_client():
  """
  接收新连接
  """
  while True:
    client, _ = g_socket_server.accept() # 阻塞,等待客户端连接
    # 加入连接池
    g_conn_pool.append(client)
    # 给每个客户端创建一个独立的线程进行管理
    thread = Thread(target=message_handle, args=(client,))
    # 设置成守护线程
    thread.setDaemon(True)
    thread.start()
 
 
def message_handle(client):
  """
  消息处理
  """
  client.sendall("连接服务器成功!".encode(encoding='utf8'))
  while True:
    bytes = client.recv(1024)
    print("客户端消息:", bytes.decode(encoding='utf8'))
    if len(bytes) == 0:
      client.close()
      # 删除连接
      g_conn_pool.remove(client)
      print("有一个客户端下线了。")
      break

设置成守护线程的目的是为了防止主线程退出之后,程序进程不退出。

消息处理这一块,如果接收到一个长度为0的数据包,那么说明客户端掉线了。实际开发中,我们一般采用心跳包机制判断客户端是否在线。

最后,调用这些方法,让服务端启动:

if __name__ == '__main__':
  init()
  # 新开一个线程,用于接收新连接
  thread = Thread(target=accept_client)
  thread.setDaemon(True)
  thread.start()
  # 主线程逻辑
  while True:
    cmd = input("""--------------------------
输入1:查看当前在线人数
输入2:给指定客户端发送消息
输入3:关闭服务端
""")
    if cmd == '1':
      print("--------------------------")
      print("当前在线人数:", len(g_conn_pool))
    elif cmd == '2':
      print("--------------------------")
      index, msg = input("请输入“索引,消息”的形式:").split(",")
      g_conn_pool[int(index)].sendall(msg.encode(encoding='utf8'))
    elif cmd == '3':
      exit()

如果对流程不清楚的话,可以再回到上面,看看文章的第二部分。

四.客户端代码

客户端这部分设计的很简单。

import socket # 导入 socket 模块
 
s = socket.socket() # 创建 socket 对象
s.connect(('127.0.0.1', 8712))
print(s.recv(1024).decode(encoding='utf8'))
s.send("连接了".encode('utf8'))
print(s.recv(1024).decode(encoding='utf8'))
input("")

最后的input是为了阻塞线程,防止程序接收到消息之后就退出了。

以上这篇python实现socket+threading处理多连接的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python中日期和时间格式化输出的方法小结
Mar 19 Python
使用Python的Django框架实现事务交易管理的教程
Apr 20 Python
Python的__builtin__模块中的一些要点知识
May 02 Python
win系统下为Python3.5安装flask-mongoengine 库
Dec 20 Python
Python抓取框架Scrapy爬虫入门:页面提取
Dec 01 Python
详谈python3 numpy-loadtxt的编码问题
Apr 29 Python
Python多继承顺序实例分析
May 26 Python
Selenium自动化测试工具使用方法汇总
Jun 12 Python
Sublime Text3最新激活注册码分享适用2020最新版 亲测可用
Nov 12 Python
安装python依赖包psycopg2来调用postgresql的操作
Jan 01 Python
Python爬虫自动化爬取b站实时弹幕实例方法
Jan 26 Python
人工智能深度学习OpenAI baselines的使用方法
May 20 Python
简单了解Django ContentType内置组件
Jul 23 #Python
50行Python代码获取高考志愿信息的实现方法
Jul 23 #Python
python设计tcp数据包协议类的例子
Jul 23 #Python
Django 缓存配置Redis使用详解
Jul 23 #Python
Flask框架中request、请求钩子、上下文用法分析
Jul 23 #Python
python 的 scapy库,实现网卡收发包的例子
Jul 23 #Python
python3+django2开发一个简单的人员管理系统过程详解
Jul 23 #Python
You might like
PHP 读取和修改大文件的某行内容的代码
2009/10/30 PHP
PHP中两个float(浮点数)比较实例分析
2015/09/27 PHP
thinkphp表单上传文件并将文件路径保存到数据库中
2016/07/28 PHP
微信公众号OAuth2.0网页授权问题浅析
2017/01/21 PHP
Yii2实现跨mysql数据库关联查询排序功能代码
2017/02/10 PHP
Yii框架实现记录日志到自定义文件的方法
2017/05/23 PHP
PHP基于面向对象封装的分页类示例
2019/03/15 PHP
JSQL 批量图片切换的实现代码
2010/05/05 Javascript
jQuery动态显示和隐藏datagrid中的某一列的方法
2013/12/11 Javascript
详细解密jsonp跨域请求
2015/04/15 Javascript
jQuery的animate函数实现图文切换动画效果
2015/05/03 Javascript
javascript中setInterval的用法
2015/07/19 Javascript
小程序开发实战:实现九宫格界面的导航的代码实现
2017/01/19 Javascript
Vue不能观察到数组length的变化
2018/06/08 Javascript
vue路由--网站导航功能详解
2019/03/29 Javascript
JQuery Ajax跨域调用和非跨域调用问题实例分析
2019/04/16 jQuery
在Python的Django框架中创建语言文件
2015/07/27 Python
深入解析Python设计模式编程中建造者模式的使用
2016/03/02 Python
python在Windows下安装setuptools(easy_install工具)步骤详解
2016/07/01 Python
Python使用QQ邮箱发送Email的方法实例
2017/02/09 Python
学习python中matplotlib绘图设置坐标轴刻度、文本
2018/02/07 Python
python3学习之Splash的安装与实例教程
2018/07/09 Python
浅谈Python采集网页时正则表达式匹配换行符的问题
2018/12/20 Python
Python利用Faiss库实现ANN近邻搜索的方法详解
2020/08/03 Python
雅诗兰黛(Estee Lauder)英国官方网站:世界顶级化妆品牌
2016/12/29 全球购物
欧洲品牌瓷器餐具网上商店:Porzellantreff.de
2018/04/04 全球购物
巴西备受欢迎的服装和生活方式品牌:FARM Rio
2020/02/04 全球购物
Java的接口和C++的虚类的相同和不同处
2014/03/27 面试题
C语言笔试题
2014/09/04 面试题
华三通信H3C面试题
2015/05/15 面试题
计算机相关的自我评价
2014/01/15 职场文书
会计员岗位职责
2014/03/15 职场文书
护理专业毕业生自荐书
2014/05/24 职场文书
大学生毕业求职信
2014/06/12 职场文书
乔迁之喜答谢词
2015/01/05 职场文书
士兵突击观后感
2015/06/16 职场文书