Python学习之路-----多进程、多线程并发TCP服务器

并发服务器

在实际的应用过程中,一个服务器总是对应不止一个客户端,并及时地为已经连上的客户端提供服务。传统的单进程服务模型已经不能满足这样的需求,因此利用多进程和多线程可以实现这样的需求。

创建TCP服务器的流程

  • 创建TCP套接字;
  • 将套接字与服务端口绑定;
  • listen(),开始监听客户端的请求;
  • accept(),接受一个链接请求,得到新的套接字和客户端的地址;
  • 使用新的套接字收发数据,通信结束后关闭套接字;

以上步骤是一个基本的模型,在实际编程过程中我们可以发现accept()是一个阻塞函数,即如果没有客户端的请求,程序会一直停在这个地方;recv()函数也是一个阻塞函数,如果没有客户端的数据到来,服务器会一直等到当前连接对应的客户端发送数据。因此一个并发服务器必须解决这些问题,即:如果有客户端链接建立后,创建一个新的进程或者线程用于当前的连接收发数据,父进程中原来的套接字依旧监听是否有其他的客户端请求

多进程TCP服务器

from socket import *
from multiprocessing import Process


def dealClient(newSocket,cliAddr):
    while True:
        recvData = newSocket.recv(1024)
        if len(recvData):
            print('收到来自%s的消息:%s' % (str(cliAddr), recvData))
        else:
            #如果数据长度为0 说明客户端断开连接,此时跳出循环关闭套接字
            print('客户端%s下线了......' % (str(cliAddr)))
            break
    newSocket.close()



def main():
    tcpSocket = socket(AF_INET,SOCK_STREAM)

    #设置套接字可以地址重用
    tcpSocket.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    serverAddr = ('127.0.0.1',8888)
    tcpSocket.bind(serverAddr)
    tcpSocket.listen(100)
    #设置监听队列长度,在linux中这个值没有太大意义,kernel有自己的值

   #为了防止服务端异常退出,因此使用try...finally,确保创建的套接字可以正常关闭
    try:
        while True:
            # 在主进程中不断接收新的连接请求
            newSocket,cliAddr = tcpSocket.accept()
            #创建子进程处理已经建立好的连接,tcpSocket依旧去监听是否有新的请求。
            p1 = Process(target=dealClient,args=(newSocket,cliAddr))
            p1.start()

            newSocket.close()
            #创建子进程后,父进程也同样拥有newSocekt,但是子进程使用accept()返回的新套接字发送数据,因此父进程要把newSocket关闭
    except:
        pass
    finally:
        tcpSocket.close()


if __name__ == '__main__':
    main()




结果:
收到来自('127.0.0.1', 57281)的消息:b'http://www.cmsoft.cn fromA'
收到来自('127.0.0.1', 57288)的消息:b'http://www.cmsoft.cn from B'
收到来自('127.0.0.1', 57295)的消息:b'http://www.cmsoft.cn from C'
客户端('127.0.0.1', 57281)下线了......
客户端('127.0.0.1', 57288)下线了......
客户端('127.0.0.1', 57295)下线了......

利用网络调试助手连接服务器可以测试结果。

123

多线程TCP服务器

把上面的进程换成线程就是多线程的服务器。

from socket import *
from threading import Thread


def dealClient(newSocket,cliAddr):
    while True:
        recvData = newSocket.recv(1024)
        if len(recvData):
            print('收到来自%s的消息:%s' % (str(cliAddr), recvData))
        else:
            #如果数据长度为0 说明客户端断开连接,此时跳出循环关闭套接字
            print('客户端%s下线了......' % (str(cliAddr)))
            break
    newSocket.close()



def main():
    tcpSocket = socket(AF_INET,SOCK_STREAM)

    #设置套接字可以地址重用
    tcpSocket.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    serverAddr = ('127.0.0.1',8888)
    tcpSocket.bind(serverAddr)
    tcpSocket.listen(100)
    #设置监听队列长度,在linux中这个值没有太大意义,kernel有自己的值

   #为了防止服务端异常退出,因此使用try...finally,确保创建的套接字可以正常关闭
    try:
        while True:
            # 在线程中不断接收新的连接请求
            newSocket,cliAddr = tcpSocket.accept()
            #创建子线程处理已经建立好的连接,tcpSocket依旧去监听是否有新的请求。
            t1 = Thread(target=dealClient,args=(newSocket,cliAddr))
            t1.start()

    except:
        pass
    finally:
        tcpSocket.close()


if __name__ == '__main__':
    main()
发布了76 篇原创文章 · 获赞 21 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/shen_chengfeng/article/details/103095161