使用Python实现多线程、多进程、异步IO的socket通信
多线程实现socket通信服务器端代码
import socket
import threading
class MyServer(object):
def __init__(self):
# 初始化socket
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置服务器IP地址
host = '192.168.152.1'
# 设置服务器端口号
port = 4321
# 绑定IP地址和端口
self.server.bind((host, port))
# 设置最大监听数
self.server.listen(5)
# 设置一个字典,用来保存每一个客户端的连接和身份信息
self.socket_mapping = {}
# 设置接收的最大字节数
self.maxSize = 1024
def run(self):
while True:
socket, addr = self.server.accept()
# 发送信息,提示客户端已成功连接
socket.send('success!'.encode('utf-8'))
# 将客户端socket等信息存入字典
self.socket_mapping[socket] = addr
# 创建线程,负责获取键盘输入并发送给客户端
threading.Thread(target=self.send_to_client, args=(socket,)).start()
# 创建线程,负责接收客户端信息并转发给其他客户端
threading.Thread(target=self.recv_from_client, args=(socket,)).start()
def send_to_client(self, socket):
"""
获取键盘输入并发送给客户端
:param socket:
:return:
"""
while True:
info = input()
if info == "quit":
socket.close()
for socket in self.socket_mapping.keys():
socket.send(info.encode("utf-8"))
def recv_from_client(self, socket):
"""
接收客户端信息并转发给其他客户端
:param socket:
:return:
"""
while True:
recv_info = socket.recv(self.maxSize).decode('utf-8')
print('client{} say: '.format(self.socket_mapping[socket]), recv_info)
for i_socket in self.socket_mapping.keys():
if i_socket != socket:
i_socket.send(recv_info.encode("utf-8"))
my_server = MyServer()
my_server.run()
多进程实现socket通信服务器端代码
存在的问题:在与客户端连通后,需要服务器先发送两条消息,之后才能正常通信。
import os
import socket
import sys
from multiprocessing import Process, Manager
class MyServer(object):
def __init__(self):
# 初始化socket
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置服务器IP地址
host = '192.168.152.1'
# 设置服务器端口号
port = 4321
# 绑定IP地址和端口
self.server.bind((host, port))
# 设置最大监听数
self.server.listen(5)
# 设置一个字典,用来保存每一个客户端的连接和身份信息
self.socket_mapping = Manager().dict()
# 设置接收的最大字节数
self.maxSize = 1024
# 进程锁
self.share_lock = Manager().Lock()
def run(self):
fn = sys.stdin.fileno()
while True:
socket, addr = self.server.accept()
# 发送信息,提示客户端已成功连接
socket.send('success!'.encode('utf-8'))
# 将客户端socket等信息存入字典
self.modify_mapping(self.socket_mapping, addr, socket, self.share_lock)
# 创建进程,负责获取键盘输入并发送给客户端
Process(target=self.send_to_client, args=(addr, fn)).start()
# 创建进程,负责接收客户端信息并转发给其他客户端
Process(target=self.recv_from_client, args=(addr,)).start()
def send_to_client(self, addr, fn):
"""
获取键盘输入并发送给客户端
:param addr:
:return:
"""
sys.stdin = os.fdopen(fn)
while True:
info = sys.stdin.readline()
if info == "quit":
self.socket_mapping[addr].close()
for socket in self.socket_mapping.values():
socket.send(info.encode("utf-8"))
def recv_from_client(self, addr):
"""
接收客户端信息并转发给其他客户端
:param addr:
:return:
"""
while True:
recv_info = self.socket_mapping.get(addr).recv(self.maxSize).decode('utf-8')
print('client{} say: '.format(addr), recv_info)
for i_addr in self.socket_mapping.keys():
if i_addr != addr:
self.socket_mapping.get(i_addr).send(recv_info.encode("utf-8"))
@staticmethod
def modify_mapping(share_var, share_key, share_value, share_lock):
# 获取锁
share_lock.acquire()
# 修改数据
share_var[share_key] = share_value
# 释放锁
share_lock.release()
if __name__ == "__main__":
my_server = MyServer()
my_server.run()
异步IO实现socket通信服务器端代码
存在的问题:通信时需要相互发送几次消息后,各自才会收到之前的消息并打印。
import socket
import asyncio
import select
class MyServer(object):
def __init__(self):
# 初始化socket
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置服务器IP地址
host = '192.168.152.1'
# 设置服务器端口号
port = 4321
# 绑定IP地址和端口
self.server.bind((host, port))
# 设置最大监听数
self.server.listen(5)
# 设置一个字典,用来保存每一个客户端的连接和身份信息
self.socket_mapping = {self.server: None} # 这里存入self.server是为了充当select.select参数
# 设置接收的最大字节数
self.maxSize = 1024
# 进入事件循环
self.loop = asyncio.get_event_loop()
def run(self):
while True:
# select监听请求对象
rret, _, _ = select.select(self.socket_mapping.keys(), [], [])
for r_socket in rret:
if r_socket is self.server:
socket, addr = r_socket.accept()
# 发送信息,提示客户端已成功连接
socket.send('success!'.encode('utf-8'))
# 将客户端socket等信息存入字典
self.socket_mapping[socket] = addr
else:
task = [self.send_to_client(r_socket), self.recv_from_client(r_socket)]
self.loop.run_until_complete(asyncio.gather(*task))
async def send_to_client(self, socket):
"""
获取键盘输入并发送给客户端
:param socket:
:return:
"""
info = input()
if info == "quit":
socket.close()
for socket in self.socket_mapping.keys():
if socket != self.server:
socket.send(info.encode("utf-8"))
async def recv_from_client(self, socket):
"""
接收客户端信息并转发给其他客户端
:param socket:
:return:
"""
recv_info = socket.recv(self.maxSize).decode('utf-8')
print('client{} say: '.format(self.socket_mapping[socket]), recv_info)
for i_socket in self.socket_mapping.keys():
if i_socket != socket and i_socket != self.server:
i_socket.send(recv_info.encode("utf-8"))
my_server = MyServer()
my_server.run()
客户端代码(使用多线程)
import socket
import threading
class MyClient(object):
def __init__(self):
# 初始化socket
self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置服务器IP地址
self.host = '192.168.152.1'
# 设置服务器端口号
self.port = 4321
# 设置接收的最大字节数
self.max_size = 1024
def run(self):
# 与服务器建立连接
self.client.connect((self.host, self.port))
# 创建线程,负责获取键盘输入并发送给服务器
threading.Thread(target=self.sned_to_server).start()
# 创建线程,接收服务器信息
threading.Thread(target=self.recv_from_server).start()
def sned_to_server(self):
"""
获取键盘输入并发送给服务器
"""
while True:
send_msg = input()
self.client.send(send_msg.encode('utf-8'))
if send_msg == 'quit':
break
self.client.close()
def recv_from_server(self):
"""
接收服务器信息
"""
while True:
recv_info = self.client.recv(self.max_size).decode('utf-8')
print('server{} say: '.format((self.host, self.port)), recv_info)
my_client = MyClient()
my_client.run()
使用Python实现多线程、多进程、异步IO的socket通信的更多相关文章
- Python学习——多线程,异步IO,生成器,协程
Python的语法是简洁的,也是难理解的. 比如yield关键字: def fun(): for i in range(5): print('test') x = yield i print('goo ...
- 多线程/多进程/异步IO
SOCK_STREAM :TCPSOCK_Dgram :UDP family=AF_INET: 服务器之间的通信AF_INET6: 服务器之间的通信AF_UNIX: Unix不同进程间的通信 永远遵循 ...
- Python之路,Day10 - 异步IO\数据库\队列\缓存
Python之路,Day9 - 异步IO\数据库\队列\缓存 本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitM ...
- Day10 - Python协程、异步IO、redis缓存、rabbitMQ队列
Python之路,Day9 - 异步IO\数据库\队列\缓存 本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitM ...
- 从Nginx的Web请求处理机制中剖析多进程、多线程、异步IO
Nginx服务器web请求处理机制 从设计架构来说,Nginx服务器是与众不同的.不同之处一方面体现在它的模块化设计,另一方面,也是最重要的一方面,体现在它对客户端请求的处理机制上. Web服务器和客 ...
- python中同步、多线程、异步IO、多线程对IO密集型的影响
目录 1.常见并发类型 2.同步版本 3.多线程 4.异步IO 5.多进程 6.总结 1.常见并发类型 I/ O密集型: 蓝色框表示程序执行工作的时间,红色框表示等待I/O操作完成的时间.此图没有按比 ...
- Python协程、异步IO
本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitMQ队列 Redis\Memcached缓存 Paramiko SS ...
- Python高级编程和异步IO并发编程
第1章 课程简介介绍如何配置系统的开发环境以及如何加入github私人仓库获取最新源码. 1-1 导学 试看 1-2 开发环境配置 1-3 资源获取方式第2章 python中一切皆对象本章节首先对比静 ...
- 【Python之路】异步IO
线程:CPU基本执行单元,可以与同属一个进程的其他线程共享资源,线程是属于进程的. 进程:资源单元,进程一般由程序.数据集.进程控制块三部分组成.一个进程默认有一个主线程, GIL:用于在进程中对所有 ...
- python 多协程异步IO爬取网页加速3倍。
from urllib import request import gevent,time from gevent import monkey#该模块让当前程序所有io操作单独标记,进行异步操作. m ...
随机推荐
- (数据科学学习手札142)dill:Python中增强版的pickle
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 大家好我是费老师,相信不少读者朋友们都在Pyth ...
- 使用J2EE 登录实例开发
我们先了解下Servlet的生命周期 Servlet部署在容器里,其生命周期由容器管理. 概括为以下几个阶段: 1)容器加载Servlet类. 当第一次有Web客户请求Servlet服务或当Web服务 ...
- Python数据科学手册-Numpy的结构化数组
结构化数组 和 记录数组 为复合的.异构的数据提供了非常有效的存储 (一般使用pandas 的 DataFrame来实现) 传入的dtpye 使用 Numpy数据类型 Character Descri ...
- Grafana Loki 架构
转载自:https://mp.weixin.qq.com/s?__biz=MzU4MjQ0MTU4Ng==&mid=2247492186&idx=2&sn=a06954384a ...
- img和div之间有间隙的原因及解决方法
div 中 存在 img标签,由于img标签的 display:inline-block 属性. #####display:inline-block布局的元素在chrome下会出现几像素的间隙,原因是 ...
- OSF--网络类型
ABR:区域边界路由器ASBR:自治区域系统边界路由器区域部署原则: 存在vlink本地网络一定是有问题的.他只是作为一种过度技术,在vlink里无法实现认证! 配置: [r2-ospf-a ...
- PAT乙级 1024 科学计数法
思路 1.尝试失败:一开始想打算把结果直接存在一个字符串中,后来发现当指数大于0的时候还需要分别考虑两种情况,工程量巨大,尝试失败,于是借鉴了其他大佬思路,写出了ac代码 2.ac思路:首先取指数的绝 ...
- 简书是如何把用户wo逼疯的
趁验证码还有一分钟时间,吐槽一下简书. 准备开始在简书写文章,遇到一些问题. 一.markdown的问题 1.不支持html 2....... 二.绑定手机--这是一个bug 我原来是使用邮箱注册的, ...
- Linux-->磁盘分区,挂载
Linux分区 原理介绍 Linux无论有几个分区,分给哪一个目录使用,他归根结底都只有一个根目录,一个独立且唯一的文件结构,Linux中每个分区都是用来组成整个文件系统的一部分. Linux采用了一 ...
- 【算法】Tarjan
参考资料: 图论相关概念 - OI WIKI | 强连通分量 - OI WIKI 初探tarjan算法 | Tarjan,你真的了解吗 一.概念 • 子图: 对一张图 \(G=(V,E)\),若存在另 ...