无法通过fsockopen连接WebSocket服务器,求PHP连接WebSocket解决方案
Fixing 400 Bad Request When Connecting to WebSocket via PHP
Your current code sends a plain HTTP GET request, but WebSocket connections require a specific handshake process with mandatory headers. That’s exactly why you’re hitting a 400 error—the server doesn’t recognize your request as a valid WebSocket initiation.
Let’s break down what’s missing and fix the code step by step:
Key Issues in Your Original Code
- You’re using
fsockopenfor an HTTPS (443) connection, which doesn’t handle SSL/TLS encryption. You need to usestream_socket_clientwith an SSL context instead. - Critical WebSocket handshake headers are missing:
Upgrade,Connection,Sec-WebSocket-Key, andSec-WebSocket-Versionare required for the server to switch protocols to WebSocket.
Corrected Working Code
// Create an SSL context for secure HTTPS connection $context = stream_context_create([ 'ssl' => [ 'verify_peer' => false, // Disable for testing; enable this in production 'verify_peer_name' => false, ] ]); // Connect to the WebSocket server over SSL $fp = stream_socket_client('ssl://cs.money:443', $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context); if (!$fp) { echo "$errstr ($errno)<br />"; } else { // Generate a random key required for WebSocket handshake $websocketKey = base64_encode(random_bytes(16)); // Build the proper WebSocket handshake request $handshakeRequest = "GET / HTTP/1.1\r\n"; $handshakeRequest .= "Host: cs.money\r\n"; $handshakeRequest .= "Upgrade: websocket\r\n"; $handshakeRequest .= "Connection: Upgrade\r\n"; $handshakeRequest .= "Sec-WebSocket-Key: $websocketKey\r\n"; $handshakeRequest .= "Sec-WebSocket-Version: 13\r\n"; $handshakeRequest .= "\r\n"; // Mark end of headers // Send the handshake request fwrite($fp, $handshakeRequest); // Read the server's handshake response $response = ''; while (!feof($fp)) { $response .= fgets($fp, 1024); // Stop reading once we reach the end of headers (double newline) if (strpos($response, "\r\n\r\n") !== false) { break; } } // Verify if handshake was successful if (strpos($response, 'HTTP/1.1 101 Switching Protocols') !== false) { echo "WebSocket handshake successful!\n"; // Note: After this, you need to encode/decode messages per WebSocket framing rules // (client messages must be masked, server messages are unmasked) } else { echo "Handshake failed. Server response:\n$response"; } fclose($fp); }
Important Post-Handshake Notes
- SSL Security: In production, enable
verify_peerandverify_peer_nameto ensure secure, verified connections—disabling them is only for testing. - WebSocket Framing: Once the handshake succeeds, you can’t send plain text directly. You need to wrap messages in WebSocket frames (with opcode, length, and masking key for client-to-server messages).
- Server-Specific Headers: Some servers may require additional headers like
Origin—if you still get errors, inspect browser WebSocket requests (via DevTools) to match the exact headers the server expects.
内容的提问来源于stack exchange,提问作者Mike Reacher
相关产品推荐
相关产品推荐

