gpt4 book ai didi

python - 另一个 'Connection reset by peer' 错误

转载 作者:太空狗 更新时间:2023-10-29 21:39:54 24 4
gpt4 key购买 nike

我正在使用 socket 模块在 python 中创建一个服务器/客户端应用程序,但无论出于何种原因,我的服务器一直终止连接。奇怪的是,这在 Windows 中可以完美运行,但在 Linux 中却不行。我到处寻找可能的解决方案,但没有一个有效。以下是利用该错误的代码的净化版本,但成功率更高。通常它永远不会起作用。希望这仍然是足够的信息。谢谢!

服务器:

import logging
import socket
import threading
import time

def getData():
HOST = "localhost"
PORT = 5454

while True:
s = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
s.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 ) #because linux doesn't like reusing addresses by default

s.bind( ( HOST, PORT ) )
logging.debug( "Server listens" )
s.listen( 5 )
conn, addr = s.accept()
logging.debug( "Client connects" )
print "Connected by,", addr

dataRequest = conn.recv( 1024 )
logging.debug( "Server received message" )

time.sleep( .01 ) #usually won't have to sample this fast

data = """Here is some data that is approximately the length
of the data that I am sending in my real server. It is a string that
doesn't contain any unordinary characters except for maybe a tab."""

if not timeThread.isAlive(): #lets client know test is over
data = "\t".join( [ data, "Terminate" ] )
conn.send( data )
s.close()
print "Finished"
print "Press Ctrl-C to quit"
break
else:
logging.debug( "Server sends data back to client" )
conn.send( data )

logging.debug( "Server closes socket" )
s.close()

def timer( t ):
start = time.time()
while ( time.time() - start ) < t:
time.sleep( .4 )
#sets flag for another thread not here

def main():
global timeThread

logging.basicConfig( filename="test.log", level=logging.DEBUG )

#time script runs for
t = 10 #usually much longer (hours)

timeThread = threading.Thread( target=timer, args=( t, ) )
dataThread = threading.Thread( target=getData, args=() )
timeThread.start()
dataThread.start()

#just for testing so I can quit threads when sockets break
while True:
time.sleep( .1 )

timeThread.join()
dataThread.join()

if __name__ == "__main__":
main()

客户:

import logging
import socket

def getData():
dataList = []
termStr = "Terminate"

data = sendDataRequest()
while termStr not in data:
dataList.append( data )
data = sendDataRequest()
dataList.append( data[ :-len( termStr )-1 ] )

def sendDataRequest():
HOST = "localhost"
PORT = 5454

s = socket.socket( socket.AF_INET, socket.SOCK_STREAM )

while True:
try:
s.connect( ( HOST, PORT ) )
break
except socket.error:
print "Connecting to server..."

logging.debug( "Client sending message" )
s.send( "Hey buddy, I need some data" ) #approximate length

try:
logging.debug( "Client starts reading from socket" )
data = s.recv( 1024 )
logging.debug( "Client done reading" )
except socket.error, e:
logging.debug( "Client throws error: %s", e )

print data

logging.debug( "Client closes socket" )
s.close()

return data

def main():
logging.basicConfig( filename="test.log", level=logging.DEBUG )
getData()

if __name__ == "__main__":
main()

编辑:添加回溯

Traceback (most recent call last):
File "client.py", line 39, in <moduel>
main()
File "client.py", line 36, in main
getData()
File "client.py", line 10, in getData
data = sendDataRequest()
File "client.py", line 28, in sendDataRequest
data = s.recv( 1024 )
socket.error: [Errno 104] Connection reset by peer

编辑:添加调试

DEBUG:root:Server listens
DEBUG:root:Client sending message
DEBUG:root:Client connects
DEBUG:root:Client starts reading from socket
DEBUG:root:Server received message
DEBUG:root:Server sends data back to client
DEBUG:root:Server closes socket
DEBUG:root:Client done reading
DEBUG:root:Server listens
DEBUG:root:Client sending message
DEBUG:root:Client connects
DEBUG:root:Client starts reading from socket
DEBUG:root:Server received message
DEBUG:root:Server sends data back to client
DEBUG:root:Client done reading
DEBUG:root:Client sending message
DEBUG:root:Client starts reading from socket
DEBUG:root:Server closes socket
DEBUG:root:Client throws error: [Errno 104] Connection reset by peer
DEBUG:root:Server listens

Tom 的理论似乎是正确的。我会想办法更​​好地关闭连接。

这没有解决,但接受的答案似乎指出了问题。

编辑:我尝试使用 Tom 的 getData() 函数,看起来服务器仍然过早地关闭了连接。应该是可重复的,因为我也无法在 Windows 中使用它。

服务器输出/回溯:

Connected by, ('127.0.0.1', 51953)
Exception in thread Thread-2:
Traceback (most recent call last):
File "/usr/lib64/python2.6/threading.py", line 532, in __bootstrap_inner
self.run()
File "/usr/lib64/python2.6/threading.py", line 484, in run
self.__target(*self.__args, **self.__kwargs)
File "server.py", line 15, in getData
s.bind( ( HOST, PORT ) )
File "<string>", line 1, in bind
error: [Errno 22] Invalid argument

客户端输出/回溯:

Here is some data that is approximately the length
of the data that I am sending in my real server. It is a string that
doesn't contain any unordinary characters except for maybe a tab.
Traceback (most recent call last):
File "client.py", line 49, in <moduel>
main()
File "client.py", line 46, in main
getData()
File "client.py", line 11, in getData
data = sendDataRequest()
File "client.py", line 37, in sendDataRequest
print data
UnboundLocalError: local variable 'data' referenced before assignment

日志:

DEBUG:root:Server listens
DEBUG:root:Client sending message
DEBUG:root:Client connects
DEBUG:root:Client starts reading from socket
DEBUG:root:Server received message
DEBUG:root:Server sends data back to client
DEBUG:root:Server closes connection
DEBUG:root:Client done reading
DEBUG:root:Client closes socket
DEBUG:root:Client sending message
DEBUG:root:Client starts reading from socket
DEBUG:root:Client throws error: [Errno 104] Connection reset by peer

更新:我使用了 Tom 的 getData() 函数,但将 s.bind() 移到了循环之前并让它开始工作。老实说,我不知道为什么会这样,所以如果有人能解释为什么服务器关闭它的客户端套接字是安全的,而不是当它关闭它的服务器套接字时,那就太好了。谢谢!

最佳答案

虽然我无法重现此问题(在 Windows 7 64 位、Python 2.7 上),但我最好的猜测是发生了以下情况:

  • 服务器监听
  • 客户端连接
  • 客户端发送“嘿伙计,我需要一些数据”
  • 服务器收到这个
  • 服务器返回数据给客户端
  • 服务器关闭套接字
  • 客户端尝试读取套接字,发现套接字已关闭
  • 客户端抛出“连接被对端重置”错误。

您从客户端添加的堆栈跟踪似乎支持这一理论。是否可以通过一些额外的日志记录或类似的方式来证明情况并非如此?

其他注意事项:如果您的客户端在收到的第一个数据中没有找到终止字符串,它会打开一个新的服务器套接字。这在我看来是错误的 - 你应该从同一个套接字读取数据,直到你拥有所有数据。

编辑:结合更多的东西:

在您的示例日志输出中,您没有更新代码,所以我看不到每个日志行的来源。但是,看起来您有 2 个并行运行的客户端(可能在不同的进程或线程中?),这看起来很可疑,这会导致:

我刚刚注意到最后一件事。在此处的示例中 https://docs.python.org/2/library/socket.html#example服务器不会关闭套接字,它会关闭通过监听套接字生成的连接。可能是您有 2 个客户端连接到同一个服务器套接字实例,当您关闭服务器套接字时,您实际上是在断开两个连接的客户端,而不仅仅是第一个。如果您正在运行多个客户端,则记录某种身份,例如。 DEBUG:root:Client(6) 完成阅读 可能有助于证明这一点。

您能否为服务器的数据线程主循环尝试以下操作,将显示问题是否与关闭监听套接字而不是连接套接字有关:


def getData():
HOST = "localhost"
PORT = 5454

s = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
# s.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 ) #because linux doesn't like reusing addresses by default
s.bind( ( HOST, PORT ) )
logging.debug( "Server listens" )
s.listen( 5 )

while True:

conn, addr = s.accept()
logging.debug( "Client connects" )
print "Connected by,", addr

dataRequest = conn.recv( 1024 )
logging.debug( "Server received message" )

time.sleep( .01 ) #usually won't have to sample this fast

data = """Here is some data that is approximately the length
of the data that I am sending in my real server. It is a string that
doesn't contain any unordinary characters except for maybe a tab."""

if not timeThread.isAlive(): #lets client know test is over
data = "\t".join( [ data, "Terminate" ] )
conn.send( data )
conn.close()
print "Finished"
print "Press Ctrl-C to quit"
break
else:
logging.debug( "Server sends data back to client" )
conn.send( data )

logging.debug( "Server closes connection" )
conn.close()

关于python - 另一个 'Connection reset by peer' 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24874894/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com