我正在编写基本的客户端服务器应用程序。在这里。
服务器:
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
但是出乎意料的是,输出是连续的,就像代码在单线程中运行一样。为什么?有人可以解释我的思想差距在哪里吗?
第二个小问题是:为什么输出有时包含空行?
答案 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)则打印它们逐行输出。