Python socket client 报错 Connection reset by peer 是什么原因?

Python socket client 报错 Connection reset by peer 是什么原因?

最近在学习 socket 网络编程,但是 socket client 在请求 socket server 的时候,有概率出现 ConnectionResetError: [Errno 54] Connection reset by peer

server 端的代码:?

import socket

import 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 encode

import 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 peer

Traceback (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

回到顶部