Python HTTPServer/Unity C#HTTPClient的TIME_WAIT中存在大量套接字



我正在尝试让Unity和Python程序通过HTTP进行通信。Unity服务器通过HTTPCient发送HTTP请求,Python程序通过HTTPServer处理该请求。我遇到的问题是,每个请求似乎都会向TIME_WAIT发送一个套接字。通信大约每秒发生20次,最终没有更多的套接字,程序停止运行。我的理解是,这个问题是由每个请求都使用了一个新的套接字而没有正确关闭它引起的,下面的Wireshark捕获似乎支持这个套接字(最后只有一个FIN-ACK,而不是我理解的TCP需要的2个(。

我正在尝试使用更少的套接字,或者更快地释放套接字,以便它们可以再次使用。我已经尝试了许多方法来缓解这个问题,包括socket.SO_REUSEADDR、连接池和保持活动连接。我怀疑我没有正确地执行其中的一个(或全部(,但我不确定如何证实这一点。下面的代码尝试实现下面的代码——不幸的是,python方面的文档有点稀疏。

void Start() {
HttpClient requester = new HttpClient();
requester.DefaultRequestHeaders.Add("Connection", "Keep-Alive");
requester.DefaultRequestHeaders.Add("Keep-Alive", "5000");
waitForClientResult(requester);
}
private async Task waitForClientResult(HttpClient requester) {
HttpResponseMessage response = await requester.GetAsync("http://127.0.0.1:5018");
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
PythonServerReturnData data = JsonUtility.FromJson<PythonServerReturnData>(responseBody);
doSomeStuffWithTheData(data);
waitForClientResult(requester);
}
agent = UnityAgentHTTP()
class UnityAgentHTTP:
def __init__(self):
self.recievedData = None
self.replyData = "ThisDataUpdatedElsewhere".encode('utf-8')
self.exit = False
self.sendThread = threading.Thread(target=self.sendOutput, name='sendThread', daemon = True)
self.sendThread.start()

def sendOutput(self):
handler = partial(UnityHTTPServer, self)
self.httpd = MyHTTPServer(('127.0.0.1', 5018), handler)
self.httpd.serve_forever()
def cleanup(self):
print("cleaning up")
self.exit = True
self.httpd.shutdown()
self.httpd.socket.close()
self.httpd.server_close()
class MyHTTPServer(HTTPServer):
allow_reuse_address = True  
def server_bind(self):
HTTPServer.server_bind(self)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# self.socket.bind(self.server_address)
class UnityHTTPServer(BaseHTTPRequestHandler):

protocol_version = 'HTTP/1.1'
def __init__(self, unityAgentHTTP: UnityAgentHTTP, *args, **kwargs):
self.unityAgentHTTP = unityAgentHTTP
super().__init__(*args, **kwargs)

def do_HEAD(self):
self.send_response(200)
self.send_header("Content-type", "application/json")
# self.send_header("Connection", "Keep-Alive")
# self.send_header("keep-alive", "timeout=5, max=30")
self.send_header("Content-Length", len(self.unityAgentHTTP.replyData) + 20) # TODO horrible hack bc i can't figure out how to count bytes objects properly 
self.end_headers()
def do_GET(self):
self.do_HEAD()
self.wfile.write(self.unityAgentHTTP.replyData)
self.close_connection = True

Wireshark捕获

可以获得这种行为的一种情况是,不重用HttpClient实例,并创建新实例(此处提供有关该主题的更多信息(。

此外,您应该在完成对response的处理后尝试处理它:

private async Task waitForClientResult(HttpClient requester) 
{
HttpResponseMessage response = await requester.GetAsync("http://127.0.0.1:5018");
try
{
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
PythonServerReturnData data = JsonUtility.FromJson<PythonServerReturnData>(responseBody);
doSomeStuffWithTheData(data);
}
finally
{
// Dispose of HttpResponseMessage to free up system resources and close network connections.
response.Dispose();
}

waitForClientResult(requester);
}

相关内容

最新更新