Node.js与Python通过WebSockets通信报错问题咨询
Got it, let's break down exactly what's happening here and how to resolve it:
The Root Cause
The error websockets.exceptions.InvalidMessage: Malformed HTTP message happens because Socket.IO is not the same as raw WebSockets. Socket.IO builds on top of WebSockets but adds its own custom handshake protocol, frame formatting, and fallback mechanisms (like long polling) that the standard websockets Python library doesn't understand. When you try to connect a raw WebSocket client to a Socket.IO server, the server sends back Socket.IO-specific handshake data that the Python client interprets as invalid HTTP.
Solution 1: Use a Python Socket.IO Client (Recommended)
The easiest fix is to use a Python library that speaks the Socket.IO protocol directly. The go-to option is python-socketio. Here's how to set it up:
Step 1: Install the Client
Run this in your terminal:
pip install python-socketio[client]
The [client] extra installs necessary transport dependencies (like websockets for WebSocket support).
Step 2: Python Client Code Example
import socketio # Create a Socket.IO client instance sio = socketio.Client() @sio.event def connect(): print("Connected to Node.js server") # Send data to the server sio.emit('message', {'key': 'value', 'data': 'Hello from Python!'}) @sio.event def disconnect(): print("Disconnected from server") # Connect to your Node.js Socket.IO server # Replace with your server's URL (use http/https, not ws/wss) sio.connect('http://localhost:3000') # Keep the client running to listen for events sio.wait()
Step 3: Verify Node.js Server Setup
Make sure your Node.js Socket.IO server is configured to accept connections (especially if dealing with cross-origin requests). A basic working example:
const { Server } = require('socket.io'); const io = new Server(3000, { cors: { origin: "*", // Allow all origins for testing; restrict in production methods: ["GET", "POST"] } }); io.on('connection', (socket) => { console.log('A Python client connected'); socket.on('message', (data) => { console.log('Received from Python:', data); }); socket.on('disconnect', () => { console.log('Python client disconnected'); }); });
Solution 2: Switch to Raw WebSockets on Both Ends
If you don't need Socket.IO's extra features and prefer raw WebSockets, adjust your Node.js server to use a raw WebSocket library like ws:
Node.js Raw WebSocket Server
const WebSocket = require('ws'); const wss = new WebSocket.Server({ port: 3000 }); wss.on('connection', (ws) => { console.log('Raw WebSocket client connected'); ws.on('message', (data) => { console.log('Received:', data.toString()); }); ws.send('Hello from Node.js!'); });
Python Raw WebSocket Client
import asyncio import websockets async def send_data(): async with websockets.connect('ws://localhost:3000') as websocket: await websocket.send('{"key": "value", "data": "Hello from Python!"}') response = await websocket.recv() print(f"Received from Node.js: {response}") asyncio.run(send_data())
Quick Troubleshooting Tips
- Double-check the connection URL: Socket.IO uses
http:///https://(notws:///wss://) for client connections, while raw WebSockets usews:///wss://. - If you hit CORS errors, update your Node.js server's CORS settings to allow your Python client's origin.
- Confirm port numbers match exactly between your Python client and Node.js server.
内容的提问来源于stack exchange,提问作者perennial_

