• 使用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()
    
  • 相关阅读:
    QUIC协议
    适合骑车时候戴的耳机怎么选,列举五款在骑行佩戴的耳机推荐
    【Unity细节】Json序列化时出现:An item with the same key has already been added. Key:
    Day692.Tomcat如何隔离Web应用 -深入拆解 Tomcat & Jetty
    2. 引用和指针
    前端一个页面依赖多个接口解决之node接口聚合
    请求转发和重定向区别
    家用电器行业智能渠道方案:数商云DMS渠道商系统实现渠道业务全流程线上化
    为什么 Spring的构造器注入不需要 @Autowired 注解
    NX/UG二次开发—3D几何—多边形内部最大圆
  • 原文地址:https://www.cnblogs.com/engpj/p/16933904.html