The following code is run as a server and browser clients connect.
However after each request the browser is showing that websocket connection is closed. I want to keep connection open in browser clients as reopening is making it slow due to network issues etc.
Earlier with Nodejs websocket servers it never closed the connections.
下面的代码在服务器和浏览器客户端连接时运行。但是,在每次请求之后,浏览器都会显示WebSocket连接已关闭。我想在浏览器客户端中保持连接打开,因为重新打开会由于网络问题等而使其变慢。
Can anybody tell me where and how socket may be getting closed:
谁能告诉我插座可能在哪里以及如何关闭:
# WSS (WS over TLS) server example, with a self-signed certificate
from common import *
from datetime import datetime
import numpy as np
import os
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from pathlib import Path
import re
import time
import os.path
from dateutil.relativedelta import relativedelta
now = datetime.now()
dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
print("Started time=", dt_string)
def decode_batch_predictions(pred):
input_len = np.ones(pred.shape[0]) * pred.shape[1]
# Use greedy search. For complex tasks, you can use beam search
results = keras.backend.ctc_decode(pred, input_length=input_len, greedy=True)[0][0][
:, :8
]
# Iterate over the results and get back the text
output_text = []
for res in results:
condition = tf.less(res, 0)
res = tf.where(condition, 1, res)
res = tf.strings.reduce_join(num_to_char(res)).numpy().decode("utf-8")
output_text.append(res)
return output_text
characters = [' ', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
characters = np.asarray(characters, dtype='<U1')
num_to_char = layers.StringLookup(
vocabulary=characters, mask_token=None, invert=True
)
prediction_model = tf.keras.models.load_model('model_prediction2')
opt = keras.optimizers.Adam()
prediction_model.compile(optimizer=opt)
gg_hashmap = None
frameinfo = getframeinfo(currentframe())
async def hello(websocket, path):
global gg_hashmap
print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
json_data = await websocket.recv()
obj = json.loads(json_data)
#print(obj, flush=True)
if ("l" in obj and obj["l"]=='license'):
res = {
'status': 1,
'python': 1,
}
json_string = json.dumps(res)
await websocket.send(json.dumps(json_string))
else:
print("In else pat")
def start_server():
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_context.load_cert_chain("bundle.pem", "key.pem");
ip = ''
if os.name == 'nt':
ip = '127.0.0.1'
else:
ip = "0.0.0.0"
start_server = websockets.serve(
hello, ip, 31334, ssl=ssl_context
)
asyncio.get_event_loop().run_until_compaserver.pyplete(start_server)
asyncio.get_event_loop().run_forever()
def main():
print("Entered main")
global gg_hashmap
gg_hashmap = getHash();
start_server()
print("Server started")
main()
更多回答
Did you try to add error handling to the hello() method? add a try except block around the websocket.recv() and send() with websockets.exceptions.ConnectionClosedError
and check what the output might be to at least provide better context to the issue.
您是否尝试将错误处理添加到Hello()方法中?使用websockets.expontions.ConnectionClosedError在websocket.recv()和Send()周围添加一个try Except块,并检查输出可能是什么,以便至少为问题提供更好的上下文。
I'm a beginner with Python. I guess some silly issue i'm missing
我是一名新手,也是一名新手。我想我漏掉了一些愚蠢的问题
The code you wrote does not explicitly close the WebSocket connection. In a typical Python WebSocket server implementation using the websockets
library, a WebSocket connection remains open unless explicitly closed by either the server or the client, or unless an unhandled exception occurs that causes the coroutine (in this case, the hello
function) to exit.
您编写的代码没有显式关闭WebSocket连接。在使用WebSockets库的典型Python WebSocket服务器实现中,WebSocket连接保持打开,除非服务器或客户端显式关闭,或者除非发生导致协程(在本例中为Hello函数)退出的未处理异常。
In your case, I would check if there is an exception that terminates the hello
coroutine, which would effectively close the WebSocket connection.
在您的例子中,我将检查是否存在终止Hello协程的异常,这将有效地关闭WebSocket连接。
Adding exception handling and logging can help you identify if this is the case, included, as commented a try except bloc.
添加异常处理和日志记录可以帮助您确定情况是否如此(包括在内),就像一个Try Expect Block评论的那样。
async def hello(websocket, path):
try:
global gg_hashmap
print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
json_data = await websocket.recv()
# rest of your code...
except Exception as e:
print(f"Exception occurred: {e}")
Check also the websockets library FAQ like:
还可以查看websockets库的常见问题解答,例如:
It includes:
它包括:
websockets takes care of closing the connection when the handler exits
In the context of the websockets
library, the "handler" refers to the coroutine that handles the WebSocket connection—in your case, the hello
function. If this function exits for any reason, the WebSocket library will automatically close the corresponding WebSocket connection.
在WebSockets库的上下文中,“处理程序”指的是处理WebSocket连接的协程--在您的例子中是Hello函数。如果此函数因任何原因退出,WebSocket库将自动关闭相应的WebSocket连接。
In your existing code, the hello
function does not have a loop to keep it running and listening for messages continuously. Once it receives a message and processes it, the function reaches its end, which would cause the WebSocket library to close the connection.
在您现有的代码中,Hello函数没有循环来使其持续运行并侦听消息。一旦它接收到一条消息并对其进行处理,该函数就会到达终点,这将导致WebSocket库关闭连接。
To keep the connection open, you could introduce a loop inside your hello
function that continues to listen for incoming messages. For example:
要保持连接打开,可以在Hello函数中引入一个循环,以继续侦听传入的消息。例如:
async def hello(websocket, path):
try:
global gg_hashmap
while True: # Loop to keep the connection open
print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
json_data = await websocket.recv()
# Your existing code...
await websocket.send(json.dumps(json_string))
except ConnectionClosedError as e:
print(f"Connection closed unexpectedly: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
Adding a while True
loop will keep the handler running, keeping the WebSocket connection open until an explicit close request is received or an exception occurs.
添加While True循环将使处理程序保持运行,使WebSocket连接保持打开状态,直到收到显式关闭请求或发生异常。
I noticed in your code that you are not importing the asyncio
module for use in the lines, which may not be executed.
我在您的代码中注意到,您没有导入用于行的asyncio模块,这些行可能无法执行。
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
Please use import asyncio
.
请使用IMPORT Asyncio。
Another point is that you should add a ping to your WebSocket client to keep the WebSocket connection active, as it closes the connection by default. Add a ping every at least 20 seconds, as in the method below:
另一点是,您应该向WebSocket客户端添加一个ping,以保持WebSocket连接处于活动状态,因为它会在默认情况下关闭连接。至少每隔20秒添加一次ping,方法如下:
async def send_ping(websocket):
while True:
await asyncio.sleep(20) # Wait for 20 seconds
ping_message = {"type": "ping"} # Create a ping message
await websocket.send(json.dumps(ping_message))
print("Sent ping message")
In this example, the send_ping
function is responsible for sending the "ping" message every 20 seconds. Periodic sending is achieved using await asyncio.sleep(20)
, which waits for 20 seconds before sending the message again. Make sure to adjust the "ping" message and processing logic in the WebSocket server as needed to fit your specific use case.
在本例中,Send_ping函数负责每隔20秒发送一次“ping”消息。定期发送是使用aWait asyncio.sleep(20)实现的,它在再次发送消息之前等待20秒。确保根据需要调整WebSocket服务器中的“ping”消息和处理逻辑,以适应您的特定用例。
WebSocket connections should ideally remain open until either the client or server decides to close them explicitly. However, in your code, I don't see any logic that explicitly closes the WebSocket connections. WebSocket connections typically close due to errors or other issues.
理想情况下,WebSocket连接应该保持打开状态,直到客户端或服务器决定显式关闭它们。然而,在您的代码中,我没有看到任何显式关闭WebSocket连接的逻辑。WebSocket连接通常会因错误或其他问题而关闭。
Here are some common reasons why WebSocket connections may be closing unexpectedly:
以下是WebSocket连接可能意外关闭的一些常见原因:
Error Handling: Check if there are any error conditions that might cause the server to close the WebSocket connections. Look for exceptions or error messages in your server logs.
错误处理:检查是否存在可能导致服务器关闭WebSocket连接的错误条件。在服务器日志中查找异常或错误消息。
Client Disconnects: WebSocket connections can be closed by the client. Ensure that your client-side code is not explicitly closing the connection.
客户端断开:客户端可以关闭WebSocket连接。确保您的客户端代码没有显式关闭连接。
Idle Timeout: Some WebSocket libraries or servers have an idle timeout setting that closes connections that have been inactive for a certain period. Check if your WebSocket server has such a setting, and if so, adjust it if needed.
空闲超时:某些WebSocket库或服务器具有空闲超时设置,用于关闭在特定时间段内处于非活动状态的连接。检查您的WebSocket服务器是否有这样的设置,如果有,请根据需要进行调整。
Network Issues: You mentioned concerns about network issues. Ensure that there are no network problems that might lead to the connections being closed.
网络问题:您提到了对网络问题的担忧。确保没有可能导致连接关闭的网络问题。
Server Crashes: If your server crashes or encounters an unhandled exception, it can result in WebSocket connections being closed. Make sure your server code is robust and handles exceptions gracefully.
服务器崩溃:如果您的服务器崩溃或遇到未处理的异常,可能会导致WebSocket连接关闭。确保您的服务器代码是健壮的,并且优雅地处理异常。
Concurrency Issues: If your server is handling multiple connections concurrently, ensure that there are no race conditions or shared resource issues that could lead to connection closures.
并发问题:如果您的服务器同时处理多个连接,请确保不存在可能导致连接关闭的争用条件或共享资源问题。
To diagnose the issue further, you can add more logging and error handling to your server code. Additionally, you may want to check the WebSocket library or framework you are using for any specific configuration options related to connection management and timeouts.
要进一步诊断问题,可以向服务器代码中添加更多日志记录和错误处理。此外,您可能希望检查您正在使用的WebSocket库或框架,以获得与连接管理和超时相关的任何特定配置选项。
I hope this code fix your problem!
我希望这个代码可以解决您的问题!
Code:
代码:
from common import *
from datetime import datetime
import numpy as np
import os
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from pathlib import Path
import re
import time
import os.path
from dateutil.relativedelta import relativedelta
now = datetime.now()
dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
def decode_batch_predictions(pred):
input_len = np.ones(pred.shape[0]) * pred.shape[1]
results = keras.backend.ctc_decode(pred, input_length=input_len, greedy=True)[0][0][:, :8]
output_text = []
for res in results:
condition = tf.less(res, 0)
res = tf.where(condition, 1, res)
res = tf.strings.reduce_join(num_to_char(res)).numpy().decode("utf-8")
output_text.append(res)
return output_text
characters = [' ', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
characters = np.asarray(characters, dtype='<U1')
num_to_char = layers.StringLookup(
vocabulary=characters, mask_token=None, invert=True
)
prediction_model = tf.keras.models.load_model('model_prediction2')
opt = keras.optimizers.Adam()
prediction_model.compile(optimizer=opt)
gg_hashmap = None
frameinfo = getframeinfo(currentframe())
async def hello(websocket, path):
global gg_hashmap
print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
json_data = await websocket.recv()
obj = json.loads(json_data)
if ("l" in obj and obj["l"] == 'license'):
res = {
'status': 1,
'python': 1,
}
json_string = json.dumps(res)
await websocket.send(json.dumps(json_string))
else:
print("In else part")
def start_server():
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_context.load_cert_chain("bundle.pem", "key.pem")
ip = ''
if os.name == 'nt':
ip = '127.0.0.1'
else:
ip = "0.0.0.0"
start_server = websockets.serve(hello, ip, 31334, ssl=ssl_context)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
def main():
global gg_hashmap
gg_hashmap = getHash()
start_server()
if __name__ == "__main__":
main()
更多回答
Beat me to it by a long shot (should've read answers before writing my own code... almost identical to what you posted). Any idea why this isn't accepted?
遥遥领先于我(我应该在编写自己的代码之前阅读答案……与您发布的内容几乎一模一样)。你知道为什么这个不被接受吗?
There is no exception as you've suggested. However the loop has solved the problem and the response is reduced from 2sec to .5 seconds due to reuse of connection. Thanks for this Loop
正如你所建议的,没有例外。然而,循环解决了这个问题,由于连接的重复使用,响应时间从2秒减少到0.5秒。谢谢你的这个循环
@user5858 Great, well done!
@user5858太棒了,干得好!
as it closes the connection by default
how fast? in milliseconds or seconds?
当它默认关闭连接时,速度有多快?以毫秒还是秒为单位?
The websocket client waits up to 2 minutes by default to close if it does not receive a response from the websocket server, but I tested and also verified that it closed well before that on a web server with apache, this type of connection changes, interfering with the response time. In this case, you must make some settings on the webapache server such as mod_proxy_wstunnel etc... What other services are you using in this application?
默认情况下,如果没有收到来自WebSocket服务器的响应,WebSocket客户端最多等待2分钟才会关闭,但我测试并验证了它关闭的时间远远早于在安装了APACHE的Web服务器上,这种类型的连接发生了变化,干扰了响应时间。在这种情况下,您必须在Webapache服务器上进行一些设置,如mod_proxy_wstunnel等。您在此应用程序中还使用了哪些其他服务?
我是一名优秀的程序员,十分优秀!