python并行套接字连接

时间:2019-05-09 19:36:45

标签: python python-3.x sockets

我正在编写基本的客户端服务器应用程序。在这里。

服务器:

import socket
from multiprocessing import Process


def process_request(conn, addr):
    print('connected client:', addr)
    with conn:
        while True:
            data = conn.recv(1024)
            if not data:
                break
            print(data.decode('utf8'))


if __name__ == '__main__':
    with socket.socket() as sock:
        sock.bind(('', 10001))
        sock.listen()
        while True:
            conn, addr = sock.accept()
            p = Process(target = process_request, args = (conn, addr))
            print('starting new process')
            p.start()
            p.join()

客户

import socket
from time import sleep
from multiprocessing import Pool


def create_socket_and_send_data(number):
    print(f'start sending data for {number}')

    with socket.create_connection(('127.0.0.1', 10001)) as sock:
        try:
            sock.sendall(f'sending data from {number} socket (1)\n'.encode('utf8'))
            sleep(2)
            sock.sendall(f'sending data from {number} socket (2)\n'.encode('utf8'))
        except socket.error as ex:
            print('send data error', ex)

    print(f'all data for {number} is sended')


if __name__ == '__main__':
    with Pool(processes=3) as pool:
        pool.map(create_socket_and_send_data, range(5))

客户端输出:

$ python 59_several_connection_client.py
start sending data for 0
start sending data for 1
start sending data for 2
all data for 0 is sended
all data for 1 is sended
all data for 2 is sended
start sending data for 3
start sending data for 4
all data for 3 is sended
all data for 4 is sended

服务器输出:

starting new process
connected client: ('127.0.0.1', 63476)
sending data from 0 socket (1)

sending data from 0 socket (2)

starting new process
connected client: ('127.0.0.1', 63477)
sending data from 1 socket (1)
sending data from 1 socket (2)

starting new process
connected client: ('127.0.0.1', 63478)
sending data from 2 socket (1)
sending data from 2 socket (2)

starting new process
connected client: ('127.0.0.1', 63479)
sending data from 3 socket (1)

sending data from 3 socket (2)

starting new process
connected client: ('127.0.0.1', 63480)
sending data from 4 socket (1)
sending data from 4 socket (2)

我有几个问题。首先,我不明白为什么输出顺序是这样的。我认为它将是:

data from socket 0 (1)
data from socket 1 (1)
data from socket 2 (1)
# now the pull is full, processes are sleeping
data from socket 0 (2)
data from socket 3 (1)
data from socket 1 (2)
data from socket 4 (1)
data from socket 2 (2)
# pay attention that pool had contained 3 processes, 
# it finished them one by one, so new places in the pool 
# were occupied by fresh processes that started to execute
# 
# now old 3 processes have been finished 
# and pull contains 2 new processes, they are sleeping
data from socket 4 (2)
data from socket 3 (2)
# all ok, 2 processes are done

但是出乎意料的是,输出是连续的,就像代码在单线程中运行一样。为什么?有人可以解释我的思想差距在哪里吗?

第二个小问题是:为什么输出有时包含空行?

1 个答案:

答案 0 :(得分:1)

  • 您只是join()太早了。您的主服务器进程会等待每个子进程完成,然后再生成新的进程,从而顺序执行。要干净地退出,可以在结束主循环执行之前收集进程并将其加入。
        processes = []
        while True:
            conn, addr = sock.accept()
            p = Process(target = process_request, args = (conn, addr))
            processes.append(p) 
            print('starting new process')
            p.start()
        for p in processes:
            p.join()

请注意,在这个最小的示例中,processes列表将永远增长。您可能还需要定期检查列表exitcode来清理列表。在这种用例中,维护过程有点繁琐,因此我也建议alternative ways在python中产生异步任务。

  • 出现空行是因为您的数据包以'\n'结尾,而print添加了额外的'\n'。因此,当包含消息的未决数据包被打印时,它跳了额外的一行。产生延迟的进程(1、2和4)一次打印两行,因为它们的数据被系统缓存到服务器端,并且每两行仅打印一次跳转,而其他进程(0和3)则打印它们逐行输出。
相关问题