使用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 ...
 
随机推荐
- paddleocr安装与图片识别快速开始
			
本文首发我的个人博客:paddleocr安装教程快速开始 1. 安装Python环境 wget https://mirrors.huaweicloud.com/python/3.8.5/Python- ...
 - Django ORM 实现数据的多表 增删改查
			
一.创建模型和表 假定下面这些概念.字段与关系: 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,手机号,家庭住址信息. 作者详情模型 和 作者模型之间是一对一的关系(one- ...
 - 学习完nio的一个小笔记吧
			
这是一个nio网络通信服务端的demo,主要就学习了selector的一些用法,以及它里面的事件类型 selector是对nio的一个优化,它能保证既能高效处理线程中的事件,又能保证线程不会一直占用c ...
 - Pod 的生命周期
			
上图展示了一个 Pod 的完整生命周期过程,其中包含 Init Container.Pod Hook.健康检查 三个主要部分,接下来我们就来分别介绍影响 Pod 生命周期的部分: 首先在介绍 Pod ...
 - EFK-4::ElasticSearch集群TLS加密通讯
			
转载自:https://mp.weixin.qq.com/s?__biz=MzUyNzk0NTI4MQ==&mid=2247483822&idx=1&sn=6813b22eb5 ...
 - CentOS无法识别NTFS格式U盘完美解决方案
			
问题描述:CentOS上无法识别NTFS格式的U盘 解决方案: # 进入yum目录 cd /etc/yum.repos.d # 下载阿里的epel wget http://mirrors.aliyun ...
 - win7通过netsh命令禁用、启用本地连接 定时关闭开启网络连接
			
1) 先检查网络接口名称 C:\Windows\system32>netsh interface show interface 管理员状态 状态 类型 接口名称 ---------------- ...
 - 在图片不被裁剪时opencv绕图片中任意点旋转任意角度
			
opencv绕图片中任意角度旋转任意角度 最近在做项目需要把把图片绕图片中任意点旋转任意角度,考虑到自己旋转需要编写插值算法,所以想到了用opencv,但是网上都是围绕图片中点旋转任意角度的,都是 ...
 - 谣言检测(GACL)《Rumor Detection on Social Media with Graph Adversarial Contrastive Learning》
			
论文信息 论文标题:Rumor Detection on Social Media with Graph AdversarialContrastive Learning论文作者:Tiening Sun ...
 - PAT (Basic Level) Practice 1032 挖掘机技术哪家强 分数 20
			
为了用事实说明挖掘机技术到底哪家强,PAT 组织了一场挖掘机技能大赛.现请你根据比赛结果统计出技术最强的那个学校. 输入格式: 输入在第 1 行给出不超过 105 的正整数 N,即参赛人数.随后 N ...