Я пытаюсь заставить программу Unity и Python общаться через HTTP. Сервер Unity отправляет HTTP-запрос через HTTPCient, который программа Python обрабатывает через HTTPServer. Проблема, с которой я столкнулся, заключается в том, что каждый запрос, похоже, отправляет сокет в TIME_WAIT. Связь происходит примерно 20 раз в секунду, и в конце концов сокетов больше нет, и программа перестает работать. Насколько я понимаю, эта проблема вызвана тем, что каждый запрос использует новый сокет без его надлежащего закрытия, что, по-видимому, поддерживает приведенный ниже захват Wireshark (в конце есть только один FIN-ACK, а не два, которые, как я понимаю, требует TCP).
Я пытаюсь использовать меньше сокетов или освободить сокеты раньше, чтобы их можно было использовать снова. Я пробовал несколько подходов к решению этой проблемы, включая 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 capture