我正在尝试制作实时应用程序。我使用 NodeJS 作为服务器和 Socket.IO,来实现我的实时功能。
问题是我收到的错误为:
WebSocket connection to 'wss://localhost:1234/socket.io/?EIO=3&transport=websocket' failed: Invalid frame header
我尝试了很多方法,例如将 https 更改为 http、降低 Socket.IO 版本等,但没有任何效果。请帮助我找出问题的原因,以便我可以查明应用程序中的错误。我不想采用其他 COMET 协议。
在服务器和客户端上使用相同版本的
socket.io
和 socket.io-client
。
这是我的错误,只是我使用 socket.io 初始化服务器两次,这导致了问题
对我来说,答案是我正在与版本 2 的客户端连接,而服务器正在运行版本 4。根据 根据文档,我必须在服务器上启用
allowEIO3
我遇到的问题是,当使用 create-react-app 并使用“npm run start”运行它以在开发过程中获取实时刷新本地版本时,它默认使用具有
/ws
路径的 websocket。这与我也使用此路径的应用程序发生冲突。因此,当您将 setupProxy.js
与 http-proxy-middleware 一起使用时,它会将两者转发到 api 服务器,这会导致无效的帧标头。
解决方案是在网络应用程序中将 websocket 路由更改为其他类似
/websocket
的内容,并在 setupProxy.js
中进行如下设置:
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
// Do not use `/ws` as it conflicts with create-react-app's hotrefresh socket.
createProxyMiddleware('/websocket', {
target: 'http://localhost:3000',
ws: true,
changeOrigin: true,
})
);
};
更改了套接字 io 以使用其独立服务器,它对我有用。最初将其添加到由express创建的服务器中。 这段代码解决了问题..
const io = require("socket.io")();
//listening socket io on different port
io.listen(4000);
我目前在使用 socket.io-client 时遇到同样的问题。我按照以下说明解决了我的问题。
您可以尝试在客户端中将 opts.transports 设置为仅 websocket:
io.connect(url, { transports: ['websocket'] }); // default is ['polling', 'websocket']
参考:https://github.com/socketio/socket.io-client/issues/1097#issuecomment-301301030
我也遇到了这个问题,但就我而言,我将文件从 javascript 发送到 python 中的 Flask 后端,并且我的块大小太大。似乎 socket.io 将通过网络发送的每帧限制为 1MB,其中包括 socket.io 标头。发送 1MB 或更大的块似乎会弄乱现有的标头,因此我减小了块大小,效果很好。
客户端(与 Socket.io CDN 版本 4.7.5 一起使用的普通 JS)
const form = document.getElementById('main-form')
form.addEventListener('submit', (e) => {
e.preventDefault();
const langSelect = document.querySelector('#language');
const language = langSelect.value;
const currencySelect = document.querySelector('#currency');
const currency = currencySelect.value;
sendFile({ language, currency });
});
const socket = io('http://localhost:5000'); // Adjust the server URL accordingly
function sendFile(moreDataObject) {
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];
if (!file) return;
// if CHUNK_SIZE >= 1MB then the socket header gets overwritten and throws errors
const CHUNK_SIZE = 1024 * 512; // 0.5MB
const totalChunks = Math.ceil(file.size / CHUNK_SIZE);
const fileId = `${file.name}-${Date.now()}`; // Unique ID for the file upload
for (let i = 0; i < totalChunks; i++) {
const blob = file.slice(i * CHUNK_SIZE, (i + 1) * CHUNK_SIZE);
const reader = new FileReader();
reader.onload = (e) => {
const base64Content = e.target.result.split(',')[1];
socket.emit('file_chunk', {
fileId: fileId,
chunkIndex: i,
totalChunks: totalChunks,
chunkData: base64Content,
fileName: file.name, // Consider sanitizing on the server
...moreDataObject // Including the language and currency
});
};
reader.readAsDataURL(blob);
}
}
服务器(使用 Flask v3.0.2、Flask-Cors v4.0.0、Flask-SocketIO v5.3.6)
import os
from flask import Flask, request
from flask_cors import CORS
from flask_socketio import SocketIO
import base64
app = Flask(__name__)
CORS(app)
socketio = SocketIO(app, cors_allowed_origins="*")
# Dictionary to hold file chunks
file_chunks = {}
@socketio.on("file_chunk")
def handle_file_chunk(data):
print(f"\n\nLanguage: {data['language']} Currency: {data['currency']}\n\n")
# Extracting the chunk data
file_id = data["fileId"]
chunk_index = data["chunkIndex"]
total_chunks = data["totalChunks"]
chunk_data = base64.b64decode(data["chunkData"])
file_name = data["fileName"] # Consider sanitizing this
# Initialize the file's chunk list if not already
if file_id not in file_chunks:
file_chunks[file_id] = [None] * total_chunks
# Store the chunk data
file_chunks[file_id][chunk_index] = chunk_data
# Check if all chunks have been received
if all(chunk is not None for chunk in file_chunks[file_id]):
upload_path = "uploads"
if not os.path.exists(upload_path):
os.makedirs(upload_path)
# Sanitize the file_name or ensure it's safe before appending it to the path
safe_file_name = os.path.join(upload_path, os.path.basename(file_name))
# Reassemble the file
with open(safe_file_name, "wb") as file:
for chunk in file_chunks[file_id]:
file.write(chunk)
print(f"Received and reassembled {safe_file_name}")
# Cleanup: remove stored chunks to free memory
del file_chunks[file_id]
if __name__ == "__main__":
socketio.run(app)