我的目标是在一台服务器和一个客户端之间建立一个连续且健壮的 TCP连接。如果一侧出现故障,另一侧应该等到它恢复。
我基于这个问题(只要求连续但不健壮的 TCP 连接并且不处理保活问题)、这篇文章和我自己的经验编写了以下代码。
我有两个问题:
我怎样才能使keepalive工作?如果服务器死了,客户端只有在尝试之后才能识别它
send()
- 这也可以在没有KEEPALIVE
选项的情况下工作,因为这会导致连接重置。是否有某种方法可以让套接字为已死的连接或我可以定期检查的某些保活功能发送中断?这是处理连续 TCP 连接的可靠方法吗?拥有稳定、连续的 TCP 连接似乎是一个标准问题,但是,我找不到详细介绍此问题的教程。必须有一些最佳实践。
请注意,我可以在应用程序级别自行处理保持活动消息。但是,由于 TCP 已经在传输层实现了这一点,因此最好依赖较低层提供的这种服务。
服务器:
from socket import *
serverPort = 12000
while True:
# 1. Configure server socket
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
serverSocket.bind(('127.0.0.1', serverPort))
serverSocket.listen(1)
print("waiting for client connecting...")
connectionSocket, addr = serverSocket.accept()
connectionSocket.setsockopt(SOL_SOCKET, SO_KEEPALIVE,1)
print(connectionSocket.getsockopt(SOL_SOCKET,SO_KEEPALIVE))
print("...connected.")
serverSocket.close() # Destroy the server socket; we don't need it anymore since we are not accepting any connections beyond this point.
# 2. communication routine
while True:
try:
sentence = connectionSocket.recv(512).decode()
except ConnectionResetError as e:
print("Client connection closed")
break
if(len(sentence)==0): # close if client closed connection
break
else:
print("recv: "+str(sentence))
# 3. proper closure
connectionSocket.shutdown(SHUT_RDWR)
connectionSocket.close()
print("connection closed.")
客户端:
from socket import *
import time
while True:
# 1. configure socket dest.
serverName = '127.0.0.1'
serverPort = 12000
clientSocket = socket(AF_INET, SOCK_STREAM)
try:
clientSocket.setsockopt(SOL_SOCKET, SO_KEEPALIVE,1)
clientSocket.connect((serverName, serverPort))
print(clientSocket.getsockopt(SOL_SOCKET,SO_KEEPALIVE))
except ConnectionRefusedError as e:
print("Server refused connection. retrying")
time.sleep(1)
continue
# 2. communication routine
while(1):
sentence = input('input sentence: ')
if(sentence == "close"):
break
try:
clientSocket.send(sentence.encode())
except ConnectionResetError as e:
print("Server connection closed")
break
# 3. proper closure
clientSocket.shutdown(SHUT_RDWR)
clientSocket.close()
我试图尽可能少地保留这个例子。但考虑到鲁棒性的要求,它相对较长。
我还尝试了一些套接字选项,如TCP_KEEPIDLE
,TCP_KEEPINTVL
和TCP_KEEPCNT
.
谢谢!