Python 通过套接字接受连接时速度慢
Python slow at accepting connections via sockets
所以首先我会描述我在做什么。
一个游戏提供了一个网络界面,但只在 IPv4 上,我希望互联网上的人也能访问它。然而,从我的 ISP 那里我只能得到 public IPv6。因为我在互联网上找不到任何东西来翻译请求和响应,所以我写了一个小应用程序来翻译。因此 IPv6 请求被转发到网络服务器,网络服务器响应被转换回 IPv6。那工作正常。
唯一令人不安的一点是......并非所有请求都被检测到或发生了什么,就像我第一次访问该网页,有时它只是挂起并说它正在等待 style.css 文件但是当我查看控制台时输出没有报告的连接。当您尝试使用 Web 界面执行某些操作时,通常会有很多延迟。
然后这是我的代码:(警告我真的不知道网络的一切到底是做什么的,尤其是关于发送的东西我不太明白是否需要它,我只是发现它在线)
def handle_request(return_address):
ipv4side = socket.create_connection(("127.0.0.1", 7245))
request = return_address.recv(2048)
print(request)
request = str(request, 'utf-8')
p = re.compile('\[[^]]*]:7250')
m = p.search(request)
request = request.replace(request[m.start():m.end()], '127.0.0.1:7245')
request = request.encode('utf-8')
msg_len = len(request)
totalsent = 0
while totalsent < msg_len:
sent = ipv4side.send(request[totalsent:])
if sent == 0:
raise RuntimeError("socket connection broken")
totalsent += sent
while True:
response = ipv4side.recv(2048)
if len(response) == 0:
ipv4side.close()
return
msg_len = len(response)
totalsent = 0
while totalsent < msg_len:
sent = return_address.send(response[totalsent:])
if sent == 0:
raise RuntimeError("socket connection broken")
totalsent += sent
ipv6side = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
ipv6side.bind((IPV6, 7250))
ipv6side.listen(20)
ipv6side.settimeout(30)
while True:
try:
connected_socket = ipv6side.accept()[0]
print("NEW CONNECTION!" + str(connected_socket))
Thread(target=handle_request, args=(connected_socket,)).start()
except socket.timeout:
print("nothing new...")
我希望任何人都可以帮助我:D
我解决了问题! (我认为)
因此,我遵循了 user253751 所说的关于如何允许 HTTP 对多个请求使用相同连接的内容,因此我进行了调整,并且现在必须检测 end-of-response/request(eor ) 的响应和请求。
我做的第一件事是将整个 handle_request 代码包装在一个 while 语句中,用于处理一个连接上的多个请求。
对于响应结束,我使用正则表达式
eor = re.compile('\r\n\r\n\Z')
然后在适当的地方:
eorm = eor.search(str(response, 'ISO-8859-1', ignore)) # I replaced the utf-8
# by the correct ISO-
# 8859-1 used for HTTP
# just to be safe
if eorm or len(response) == 0:
safe_send(return_address, response)
ipv4side.close()
break
对于请求结束,它基本上是相同的,只是看起来请求的长度为 0。
负责发送的代码我放入了接受连接和消息的 safe_send 函数中。
Aa 并且我对其进行了编码,以便万一服务器由于某种原因中止连接并因此在尝试接收时抛出错误,它会在新连接上重新发送请求。
try:
response = ipv4side.recv(2048)
except ConnectionAbortedError:
ipv4side = socket.create_connection(("127.0.0.1", 7245))
safe_send(ipv4side, request)
continue
我希望这是一个很好的解释:]
所以首先我会描述我在做什么。
一个游戏提供了一个网络界面,但只在 IPv4 上,我希望互联网上的人也能访问它。然而,从我的 ISP 那里我只能得到 public IPv6。因为我在互联网上找不到任何东西来翻译请求和响应,所以我写了一个小应用程序来翻译。因此 IPv6 请求被转发到网络服务器,网络服务器响应被转换回 IPv6。那工作正常。 唯一令人不安的一点是......并非所有请求都被检测到或发生了什么,就像我第一次访问该网页,有时它只是挂起并说它正在等待 style.css 文件但是当我查看控制台时输出没有报告的连接。当您尝试使用 Web 界面执行某些操作时,通常会有很多延迟。
然后这是我的代码:(警告我真的不知道网络的一切到底是做什么的,尤其是关于发送的东西我不太明白是否需要它,我只是发现它在线)
def handle_request(return_address):
ipv4side = socket.create_connection(("127.0.0.1", 7245))
request = return_address.recv(2048)
print(request)
request = str(request, 'utf-8')
p = re.compile('\[[^]]*]:7250')
m = p.search(request)
request = request.replace(request[m.start():m.end()], '127.0.0.1:7245')
request = request.encode('utf-8')
msg_len = len(request)
totalsent = 0
while totalsent < msg_len:
sent = ipv4side.send(request[totalsent:])
if sent == 0:
raise RuntimeError("socket connection broken")
totalsent += sent
while True:
response = ipv4side.recv(2048)
if len(response) == 0:
ipv4side.close()
return
msg_len = len(response)
totalsent = 0
while totalsent < msg_len:
sent = return_address.send(response[totalsent:])
if sent == 0:
raise RuntimeError("socket connection broken")
totalsent += sent
ipv6side = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
ipv6side.bind((IPV6, 7250))
ipv6side.listen(20)
ipv6side.settimeout(30)
while True:
try:
connected_socket = ipv6side.accept()[0]
print("NEW CONNECTION!" + str(connected_socket))
Thread(target=handle_request, args=(connected_socket,)).start()
except socket.timeout:
print("nothing new...")
我希望任何人都可以帮助我:D
我解决了问题! (我认为)
因此,我遵循了 user253751 所说的关于如何允许 HTTP 对多个请求使用相同连接的内容,因此我进行了调整,并且现在必须检测 end-of-response/request(eor ) 的响应和请求。 我做的第一件事是将整个 handle_request 代码包装在一个 while 语句中,用于处理一个连接上的多个请求。
对于响应结束,我使用正则表达式
eor = re.compile('\r\n\r\n\Z')
然后在适当的地方:
eorm = eor.search(str(response, 'ISO-8859-1', ignore)) # I replaced the utf-8
# by the correct ISO-
# 8859-1 used for HTTP
# just to be safe
if eorm or len(response) == 0:
safe_send(return_address, response)
ipv4side.close()
break
对于请求结束,它基本上是相同的,只是看起来请求的长度为 0。 负责发送的代码我放入了接受连接和消息的 safe_send 函数中。
Aa 并且我对其进行了编码,以便万一服务器由于某种原因中止连接并因此在尝试接收时抛出错误,它会在新连接上重新发送请求。
try:
response = ipv4side.recv(2048)
except ConnectionAbortedError:
ipv4side = socket.create_connection(("127.0.0.1", 7245))
safe_send(ipv4side, request)
continue
我希望这是一个很好的解释:]