python实现tcp socket多连接通信---进程、线程、协程

news/2024/5/17 18:51:14 标签: python, socket, tcp

利用python实现socket通信,需要实现客户端和服务端。通常,服务端不仅仅是为一个客户端服务,可能同时为多个客户端提供连接服务,在python中常见的提供多连接的方式有进程、线程、协程以及select和poll实现的异步I/O。这篇文章,主要介绍使用进程、线程、协程实现的socket多连接通信。

首先,这里先介绍一下进程、线程、协程的区别?(https://my.oschina.net/u/4543837/blog/4465255

进程:操作系统提供的抽象概念,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。程序是指令、数据及其组织形式的描述,进程是程序的实体。程序本身是没有生命周期的,它只是存在磁盘上的一些指令,程序一旦运行就是进程。

线程:也是操作系统提供的抽象概念,是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。一个进程可以有一个或多个线程,同一进程中的多个线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。

协程(Coroutine,又称微线程)是一种比线程更加轻量级的存在,协程不是被操作系统内核所管理,而完全是由程序所控制。协程与线程以及进程的关系见下图所示。

4e4aa4ae6a4138b8afdd6c8650738530bba.png

  • 协程可以比作子程序,但执行过程中,子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。协程之间的切换不需要涉及任何系统调用或任何阻塞调用

  • 协程只在一个线程中执行,是子程序之间的切换,发生在用户态上。而且,线程的阻塞状态是由操作系统内核来完成,发生在内核态上,因此协程相比线程节省线程创建和切换的开销

  • 协程中不存在同时写变量冲突,因此,也就不需要用来守卫关键区块的同步性原语,比如互斥锁、信号量等,并且不需要来自操作系统的支持。

协程适用于IO阻塞且需要大量并发的场景,当发生IO阻塞,由协程的调度器进行调度,通过将数据流yield掉,并且记录当前栈上的数据,阻塞完后立刻再通过线程恢复栈,并把阻塞的结果放到这个线程上去运行。

进程实现tcp socket通信

server

python">import socket
from multiprocessing import Process


class ServerProcess:
    def __init__(self, ipaddr, port, num):
        self.ipaddr = ipaddr
        self.port = port
        self.num = num

    # 服务端的数据接收,在调用时使用多进程
    def server_link(self, conn, addr):
        conn.send("Welcome connect!".encode())

        while True:
            try:
                data = conn.recv(1024)
                if data:
                    print("from {0}:".format(addr), data.decode('utf-8'))
                else:
                    break
            except Exception:
                break

        conn.close()

    # 服务端的启动程序
    def server_start(self):
        # IPv4
        s_pro = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 操作系统会在服务器socket被关闭或服务器进程终止后马上释放该服务器的端口
        s_pro.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s_pro.bind((self.ipaddr, self.port))
        s_pro.listen(self.num)
        print('Waiting link...')
        while True:
            conn, addr = s_pro.accept()
            print("Success connect from ", addr)
            # 启动多进程实现多连接
            p = Process(target=self.server_link, args=(conn, addr))
            p.start()


if __name__ == '__main__':
    server = ServerProcess('127.0.0.1', 12345, 5)
    server.server_start()

线程实现tcp socket通信

server

python">import socket
import threading


class ServerThread:
    def __init__(self, ipaddr, port, num):
        self.ipaddr = ipaddr
        self.port = port
        self.num = num

    def server_link(self, conn, addr):
        conn.send("Welcome connect!".encode())

        while True:
            try:
                data = conn.recv(1024)
                if data:
                    print("from {0}:".format(addr), data.decode('utf-8'))
                else:
                    break
            except Exception:
                break

        conn.close()

    def server_start(self):
        s_pro = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s_pro.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s_pro.bind((self.ipaddr, self.port))
        s_pro.listen(self.num)
        print('Waiting link...')
        while True:
            conn, addr = s_pro.accept()
            print("Success connect from ", addr)
            p = threading.Thread(target=self.server_link, args=(conn, addr))
            p.start()


if __name__ == '__main__':
    server = ServerThread('127.0.0.1', 12345, 5)
    server.server_start()

协程实现tcp socket通信

server

python">import socket
import asyncio


class ServerProcess:
    def __init__(self, ipaddr, port, num):
        self.ipaddr = ipaddr
        self.port = port
        self.num = num

    async def server_link(self, conn, addr):
        conn.send("Welcome connect!".encode())

        while True:
            try:
                data = conn.recv(1024)
                if data:
                    print("from {0}:".format(addr), data.decode('utf-8'))
                else:
                    break
            except Exception:
                break

        conn.close()

    def server_start(self):
        s_pro = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s_pro.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s_pro.bind((self.ipaddr, self.port))
        s_pro.listen(self.num)
        print('Waiting link...')
        while True:
            conn, addr = s_pro.accept()
            print("Success connect from ", addr)
            loop = asyncio.get_event_loop()
            loop.run_until_complete(self.server_link(conn, addr))


if __name__ == '__main__':
    server = ServerProcess('127.0.0.1', 12345, 5)
    server.server_start()

对于以上三种方式实现的服务端,客户端这里我都采用同样的代码,可以写多个客户端测试socket通信的并发性。

client

python">import socket


class Client1:
    def __init__(self, ipaddr, port):
        self.ipaddr = ipaddr
        self.port = port

    def client_link(self):
        c1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        c1.connect((self.ipaddr, self.port))
        print('receive info:', c1.recv(1024).decode('utf-8'))
        while True:
            info = input('enter info:')
            c1.send(info.encode())


if __name__ == '__main__':
    c = Client1('127.0.0.1', 8888)
    c.client_link()

 


http://www.niftyadmin.cn/n/1220999.html

相关文章

生成器实现协程的行为

1、例子中的c.send(None),其功能类似于next(c),比如: >>> def num():yield 1yield 2>>> c num() >>> c.send(None) 1 >>> c.send(None) 2 >>> c.send(None) Traceback (most recent call las…

Linux下Java获取本机IP地址

转载:http://blog.163.com/cvskill126/blog/static/38147380200973015928123/ 在Linux下用InetAddress.getLocalHost()方法获取本机IP地址, 得到的结果总是:127.0.0.1。 原来这个是etc/hosts文件中的配置,并非网卡的IP地址。 后来…

【原创翻译】命令行终端

2019独角兽企业重金招聘Python工程师标准>>> 如今,我们跟计算机的绝大部分交互都是通过图形界面(GUI)完成的。我们用键盘、鼠标和触摸屏,跟展示在屏幕上的可视化按钮或其他控件交互。 但这并不是绝对。在图形界面出现之…

python udp socket解决服务端响应时间长的指数退避算法

UDP连接是一个不可靠的连接,也就是说,UDP通信过程中可能出现数据包丢失的情况,或者是服务端宕机后,客户端不知道服务端状态,仍然不停的访问服务端的情况。针对这一情况,UDP客户端必须选择一个等待时间&…

extjs两行tbar的问题

知道每个panel都有一个tbar(top bar 上面工具栏) ,bbar(bottom bar 底部工具栏)下面为大家介绍下extjs的两个tbar问题,感兴趣的朋友可以参考下版本:extjs3.4 接触过extjs的同志们都知道每个panel都有一个tbar(top bar 上面工具栏) ,bbar(bottom bar 底部…

中国百佳产业集群名单

一、浙江省 温州鹿城区 1、中国皮鞋产业集群 2、中国打火机产业集群 温州龙湾区 3、中国人造革产业集群 瑞安市 4、中国汽车摩托车配件产业集群 5、中国休闲鞋产业集群 苍南县 6、中国印刷产业集群 温州瓯海区 7、中国锁具产业集群 乐清市 8、中国中低压电器产业集群 永嘉县 9、…

python Memcached用法示例

memcache是一套分布式的高速缓存系统,由LiveJournal的Brad Fitzpatrick开发,但目前被许多网站使用以提升网站的访问速度,尤其对于一些大型的、需要频繁访问数据库的网站访问速度提升效果十分显著。 MemCache的工作流程如下:先检查…

JAVA实现实用的ZIP压缩与解压

程序实现了ZIP压缩。共分为2部分 : 压缩(compression)与解压(decompression) 大致功能包括用了多态,递归等JAVA核心技术,可以对单个文件和任意级联文件夹进行压缩和解压。 需在代码中自定义源…