[英]python - Why does TCP client slow down then produce OSError: [Errno 99] Cannot assign requested address
I am writing a server for an event-based simulator and am using asyncio
TCP server for this purpose. 我正在为基于事件的模拟器编写服务器,并且为此目的使用了asyncio
TCP服务器。
#server.py
import asyncio
import itertools
import json
class Server:
def __init__(self, loop=None):
self.loop = loop
self.pq = asyncio.PriorityQueue()
self.counter = itertools.count()
async def __call__(self, reader, writer):
event = await reader.read(100)
message = json.loads(event.decode())
self.pq.put_nowait([next(self.counter), message])
while self.pq.qsize():
t = await self.pq.get()
send_data = json.dumps(t).encode("utf-8")
writer.write(send_data)
await writer.drain()
loop = asyncio.get_event_loop()
s = Server(loop)
coro = asyncio.start_server(s, '127.0.0.1', 5000, loop=loop)
server = loop.run_until_complete(coro)
# Serve requests until Ctrl+C is pressed
print('Serving on {}'.format(server.sockets[0].getsockname()))
try:
loop.run_forever()
except KeyboardInterrupt:
pass
# Close the server
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
I want a client to send encoded json events to this server quickly. 我希望客户端将编码的json事件快速发送到此服务器。
#client.py
import socket
import json
import datetime
host = "127.0.0.1"
port = 5000
N = 10000
start = datetime.datetime.utcnow()
for i in range(1, N + 1):
s = socket.create_connection((host, port))
send_message = {"id": i, "value": i * 3}
send_json = json.dumps(send_message)
send_data = send_json.encode("utf-8")
s.sendall(send_data)
receive_data = s.recv(1024)
receive_json = receive_data.decode("utf-8")
_ = json.loads(receive_json)
s.close()
stop = datetime.datetime.utcnow()
print("Tasks per second: {}".format(N / (stop - start).total_seconds()))
Problem The client program has varying performance and error generation, despite having no other user programs open. 问题尽管没有打开其他用户程序,该客户端程序仍具有不同的性能和错误生成。
Often, but not always, the first run of client.py
runs at about 3,000 tasks per second. 通常,但并非总是如此,第一次运行client.py
速度约为每秒3,000个任务。 Occasionally, the first run goes slower (~500-600 tasks per second). 有时,第一次运行会变慢(每秒约500-600个任务)。
Once the performance drops to 500-600 tasks per second, further runs never recover back to 3,000 tasks per second. 一旦性能下降到每秒500-600个任务,进一步的运行就永远不会恢复到每秒3,000个任务。
Eventually, running client.py
raises the following exception: 最终,运行client.py
会引发以下异常:
Traceback (most recent call last):
File "aioclient.py", line 12, in <module>
s = socket.create_connection((host, port))
File "/home/randm/Libraries/anaconda3/lib/python3.6/socket.py", line 724, in create_connection
raise err
File "/home/randm/Libraries/anaconda3/lib/python3.6/socket.py", line 713, in create_connection
sock.connect(sa)
OSError: [Errno 99] Cannot assign requested address
Question 题
How should I rewrite client.py
(or server.py
) to avoid this? 我应该如何重写client.py
(或server.py
)以避免这种情况?
Having read https://docs.python.org/3/howto/sockets.html , perhaps a few notes: 阅读了https://docs.python.org/3/howto/sockets.html ,也许有几点注意事项:
I think using a message delimiter (I've chosen b'\\x1e'
) allows me to have 1 connection for the entire set of messages instead of establishing a new connection for each message. 我认为使用消息定界符(我选择b'\\x1e'
)使我可以为整个消息集建立1个连接,而不是为每个消息建立新的连接。 The StreamReader.readuntil
method works fine in this case. 在这种情况下, StreamReader.readuntil
方法可以正常工作。
# server.py
import asyncio
import itertools
import json
PQ = asyncio.PriorityQueue()
COUNTER = itertools.count()
async def handle_data_provider(reader, writer):
try:
while True:
data = await reader.readuntil(b'\x1e')
message = json.loads(data[:-1].decode())
n = next(COUNTER)
if n % 10000 == 0:
print(n, PQ.qsize())
PQ.put_nowait([n, message])
except asyncio.streams.IncompleteReadError:
pass
loop = asyncio.get_event_loop()
coro = asyncio.start_server(handle_data_provider, '127.0.0.1', 5000, loop=loop)
server = loop.run_until_complete(coro)
# Serve requests until Ctrl+C is pressed
print('Serving on {}'.format(server.sockets[0].getsockname()))
try:
loop.run_forever()
except KeyboardInterrupt:
pass
# Close the server
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
And client... 还有客户
# client.py
import socket
import json
import datetime
host = "127.0.0.1"
port = 5000
N = 10000
start = datetime.datetime.utcnow()
s = socket.create_connection((host, port))
for i in range(1, N + 1):
message = {"id": i, "value": i * 3}
json_message = json.dumps(message)
data = json_message.encode("utf-8") + b'\x1e'
s.sendall(data)
s.close()
stop = datetime.datetime.utcnow()
print("Tasks per second: {}".format(N / (stop - start).total_seconds()))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.