基于WebSocket的视频聊天项目服务器连接400错误排查求助
Hey there, let's work through this WebSocket handshake error you're facing. Localhost works perfectly, so the issue is almost certainly tied to how NGINX is proxying your Socket.io/WebSocket traffic. Let's break down the fixes step by step:
1. Fix NGINX Configuration (Critical!)
Socket.io uses HTTP upgrade requests to switch from HTTP to WebSocket, and NGINX needs explicit config to handle this. Here's a complete, Socket.io-compatible NGINX block for your domain:
server { listen 443 ssl; server_name tensy.org; # Your existing SSL config (keep this!) ssl_certificate /path/to/your/ssl/cert.pem; ssl_certificate_key /path/to/your/ssl/key.pem; # Proxy for Socket.io namespace /space location /space { proxy_pass http://localhost:YOUR_NODE_SERVER_PORT; # Replace with your actual Node port proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # Long timeouts for video chat (avoids unexpected disconnects) proxy_connect_timeout 7d; proxy_send_timeout 7d; proxy_read_timeout 7d; } # Serve your React build files location / { root /path/to/your/react/app/build; try_files $uri $uri/ /index.html; } }
Key Config Notes:
proxy_http_version 1.1and theUpgrade/Connectionheaders are mandatory for WebSocket handshake to work.- The long timeout values prevent NGINX from dropping the persistent video chat connection.
- Double-check that
proxy_passpoints to your running Node.js server's correct port.
2. Validate Socket.io Server Setup
Make sure your Node.js server is configured to handle CORS (even for same-domain, it's safe to explicitly allow) and the /space namespace:
const io = require('socket.io')(yourServerInstance, { cors: { origin: "https://tensy.org", methods: ["GET", "POST"] } }); // Initialize the /space namespace const spaceNamespace = io.of('/space'); spaceNamespace.on('connection', (socket) => { console.log('User connected to space namespace'); // Handle your call/answer/candidate events here });
3. Clean Up React Component Code
Your component has a few anti-patterns that could contribute to timing issues:
Replace componentWillMount with componentDidMount
componentWillMount is deprecated in React 17+ and runs before the DOM is ready. Switch to componentDidMount to ensure elements like <video id="local"> exist before you try to access them:
componentDidMount() { let _position = document.location.pathname.split('/').pop(); console.log(_position); // All your WebRTC/Socket.io setup code goes here... }
Remove $(document).ready() Wrappers
React's lifecycle already ensures the DOM is ready when componentDidMount runs. The jQuery wrapper can delay socket event listeners, leading to missed handshake messages:
// Instead of this: $(document).ready(function() { socket.on('answer', function(mes) { ... }); }); // Do this directly in componentDidMount: socket.on('answer', (mes) => { console.log('Client 1', mes); peer.setRemoteDescription(JSON.parse(mes['description'])) .then(() => addcandidate(candidatee)); });
Fix the addcandidate Recursion
Your current addcandidate function can loop infinitely if candidatee never arrives. Add a retry limit to prevent this:
function addcandidate(data, retries = 0) { console.log('Candidate', data); setTimeout(() => { if (candidatee) { console.log('!', candidatee); peer.addIceCandidate(JSON.parse(candidatee)); } else if (retries < 10) { // Max 10 retries (adjust as needed) addcandidate(data, retries + 1); } else { console.error('Failed to retrieve ICE candidate after multiple attempts'); } }, 100); }
4. Troubleshooting Steps if Issues Persist
- Check NGINX error logs (
/var/log/nginx/error.log) for specific handshake failure details. - Use your browser's Network tab to inspect the WebSocket request: verify the
Upgrade: websocketandConnection: upgradeheaders are present in the request, and that the response doesn't have additional error context. - Confirm your Node.js server is running and accessible directly (try hitting
http://tensy.org:YOUR_NODE_PORT/spaceto see if it responds).
内容的提问来源于stack exchange,提问作者Alex Poloz




