Python socket client 报错 Connection reset by peer 是什么原因?
最近在学习 socket 网络编程,但是 socket client 在请求 socket server 的时候,有概率出现 ConnectionResetError: [Errno 54] Connection reset by peer
server 端的代码:?
import socketimport sys
import time
import threading
from loguru import logger
from concurrent.futures import ThreadPoolExecutor
from concurrent.futures._base import Future
default_encoding: str = 'utf-8'
pool = ThreadPoolExecutor(
max_workers=20,
thread_name_prefix='simple-work-thread-pool'
)
def init_serversocket() -> socket.socket:
serversocket = socket.socket(
family=socket.AF_INET,
type=socket.SOCK_STREAM
)
# 获取本地主机名
host = socket.gethostname()
logger.debug(f'host {host}')
port = 9999
# 绑定端口号
serversocket.bind(('0.0.0.0', port))
# 设置最大连接数,超过后排队
serversocket.listen(5)
return serversocket
def send_response(clientsocket: socket.socket, addr: tuple, response_body: bytes) -> int:
send_len: int = clientsocket.send(response_body)
clientsocket.close()
return send_len
def start_request(clientsocket: socket.socket, addr: tuple) -> int:
try:
logger.debug(f'get message from {addr}')
request_body: bytes = clientsocket.recv(2048)
request_text: str = request_body.decode(encoding=default_encoding)
response_text: str = f'server get message: {request_text}'
response_body: bytes = response_text.encode(default_encoding)
time.sleep(1)
return send_response(clientsocket=clientsocket, addr=addr, response_body=response_body)
except Exception as error:
logger.exception(error)
def start_request_callback(future: Future) -> None:
send_len: int = future.result()
logger.debug(
f'{threading.current_thread().name}, send payload len is {send_len}')
serversocket = init_serversocket()
while True:
clientsocket, addr = serversocket.accept()
clientsocket: socket.socket
addr: tuple
future: Future = pool.submit(start_request, clientsocket, addr)
future.add_done_callback(start_request_callback)
服务端使用线程池模型:主线程监听 serversocket,并把 serversocket.accept() 之后的 clientsocket 提交到线程池中处理
client 端的代码 ?
from base64 import encodeimport socket # 客户端 发送一个数据,再接收一个数据
import json
from loguru import logger
from concurrent.futures import ThreadPoolExecutor
def send_request(index:int):
try:
# 声明socket类型,同时生成链接对象
clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocket.connect(('127.0.0.1', 9999)) # 建立一个链接,连接到本地的6969端口
payload = b'ponponon'
clientsocket.send(payload)
data = clientsocket.recv(1024)
payload = data.decode()
logger.debug(f'>>> {index} {payload}')
clientsocket.close()
except Exception as error:
logger.exception(error)
pool = ThreadPoolExecutor(max_workers=100)
for i in range(100):
pool.submit(send_request,i)
# pool.shutdown(wait=True)
client 也是使用线程池并发请求 server
但是很奇怪,会随机报错,请求 100 次,会错 1-60 次,反正没有一次全通过过。但也没有 100 个请求都报错
平均请求 100 次,会报错 20次的样子!
为什么??
报错的具体内容如下:?
2022-07-08 13:00:54.957 | ERROR | __main__:send_request:26 - [Errno 54] Connection reset by peerTraceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/threading.py", line 973, in _bootstrap
self._bootstrap_inner()
│ └ <function Thread._bootstrap_inner at 0x102c7b910>
└ <Thread(ThreadPoolExecutor-0_3, started 6198751232)>
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/threading.py", line 1016, in _bootstrap_inner
self.run()
│ └ <function Thread.run at 0x102c7b640>
└ <Thread(ThreadPoolExecutor-0_3, started 6198751232)>
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/threading.py", line 953, in run
self._target(*self._args, **self._kwargs)
│ │ │ │ │ └ {}
│ │ │ │ └ <Thread(ThreadPoolExecutor-0_3, started 6198751232)>
│ │ │ └ (<weakref at 0x10393ee30; to 'ThreadPoolExecutor' at 0x102ae7d00>, <_queue.SimpleQueue object at 0x102b186d0>, None, ())
│ │ └ <Thread(ThreadPoolExecutor-0_3, started 6198751232)>
│ └ <function _worker at 0x10394cca0>
└ <Thread(ThreadPoolExecutor-0_3, started 6198751232)>
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/concurrent/futures/thread.py", line 83, in _worker
work_item.run()
│ └ <function _WorkItem.run at 0x10394cdc0>
└ <concurrent.futures.thread._WorkItem object at 0x103950880>
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
│ │ │ │ │ └ {}
│ │ │ │ └ <concurrent.futures.thread._WorkItem object at 0x103950880>
│ │ │ └ (3,)
│ │ └ <concurrent.futures.thread._WorkItem object at 0x103950880>
│ └ <function send_request at 0x102b03910>
└ <concurrent.futures.thread._WorkItem object at 0x103950880>
> File "/Users/ponponon/Desktop/code/me/http_wsgi_asgi_tutorial/003_socket_tcp_client_select.py", line 18, in send_request
data = clientsocket.recv(1024)
│ └ <method 'recv' of '_socket.socket' objects>
└ <socket.socket fd=6, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 59353)>
ConnectionResetError: [Errno 54] Connection reset by peer
我本以为是 server 处理不过来,所以导致 client 报错 [Errno 54] Connection reset by peer
但是通过查阅资料发现,tcp 的三次握手这些都是 os 来负责的。serversocket.accept()
也只是从 全连接队列 里面取连接而已。
所以我想不通是什么原因会导致这个错误发生?
回答:
好像和 listen 的大小有关系
# 设置最大连接数,超过后排队serversocket.listen(100)
设置为 100 后就没有出现过
回答:
是不是server端放在公网服务器上,client端在本地。如果是的话,建议两个端都放在本地测看看。
回答:
你的例子在我的mac上跑是ok的,会不会是服务端的并发连接数超过了其承载量,例子中是100应该不至于,直接把池改小试试吧,没准呢。
以上是 Python socket client 报错 Connection reset by peer 是什么原因? 的全部内容, 来源链接: utcz.com/p/938570.html