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

本文介绍了如何使用Python的进程、线程和协程实现TCP Socket的多连接服务。通过创建ServerProcess、ServerThread和ServerProcess类,分别展示了在多进程、多线程和异步协程环境下处理Socket连接的方法。在多进程和多线程中,服务端为每个客户端创建新的进程或线程,而在协程中,服务端利用asyncio事件循环处理并发连接,避免了线程和进程的创建开销。
摘要由CSDN通过智能技术生成

利用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

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

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

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

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()

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

楊木木8023

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值