How to use cUrl and WebSocket: https://www.youtube.com/watch?v=NLIhd0wYO24&ab_channel=DanielStenberg
Connecting to WebSocket via PHP and cURL. Connection is successful and the connection speed is good. First chunk of frames of 1024B is taken fine, second one (774B) arrived as expected. Then getting error #23 “Failure writing output to destination” and connection is interrupted. I am returning same content length for both chunks/frames. I am not able to send “HeartBeat” to keep the connection alive as well.
I also tried to Win 10, XAMPP, PHP 8.2, cUrl verion 8.3.0 in CLI mode with local admin rights. Identical result. Tried with root sudo user. Same.
// URL and parameters
$url = 'https://www.example.com/?example_param=xxxx-xxxx';
$accessToken = 'xxxxxxxxxxx';
$webSocketKey = 'lSZolfGbvpepiTeZzjGomg==';
// Headers
$headers = [
'Upgrade: websocket',
'Connection: Upgrade',
'Authorization: Bearer ' . $accessToken,
'Sec-WebSocket-Key: ' . $webSocketKey,
'Sec-WebSocket-Version: 13',
];
// cURL initialization
echo 'Init...START' . PHP_EOL;
$ch = curl_init();
echo 'Init...END' . PHP_EOL;
$outputJsonFile = __DIR__ . DIRECTORY_SEPARATOR . '_json.log';
$outputFile = __DIR__ . DIRECTORY_SEPARATOR . '_data.log';
$fileHandle = fopen($outputFile, 'w');
if ($fileHandle === false) {
trigger_error('File err', E_USER_ERROR);
}
$objThis = new stdClass();
$objThis->result = '';
$objThis->strLen = 0;
$objThis->readCalls = 0;
$objThis->headers = '';
$callback = function ($ch, $str) use (&$objThis)
{
// $objThis->result .= $str;
$strTmp = trim(preg_replace('/[[:^print:]]/', '', $str), '~'); // should be aA
// $strTmp = trim($str, "x00xff");
$objThis->result .= $strTmp;
$strLen = mb_strlen($str, '8bit'); // Same as strlen()
$objThis->strLen += $strLen;
echo PHP_EOL . '$result(cleaned)=' . (int)strlen($objThis->result) . PHP_EOL;
echo PHP_EOL . '$str[' . mb_strlen($str) . '-' . mb_strlen($str, '8bit') . '-' . $strLen . ']=' . (int)strlen($str) . PHP_EOL;
echo PHP_EOL . '$callback=' . $strTmp . PHP_EOL;
return $objThis->strLen; //return the exact length
};
$callbackRead = function ($ch, $fh, $length) use (&$objThis)
{
$objThis->readCalls++;
return fread($fh, $length); // return 'PING';
};
$callbackHeader = function ($ch, $headerLine) use (&$objThis)
{
$objThis->headers .= $headerLine;
if (trim($headerLine) === 'Upgrade: websocket') {
echo PHP_EOL . '#Connected!#' . PHP_EOL;
}
return strlen($headerLine);
};
$fR = tmpfile();
fwrite($fR, 'HeartBeat');
// Reset the file pointer
fseek($fR, 0);
// Set cURL options
$rO = curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true, // Return response as string
CURLOPT_HTTPHEADER => $headers,
CURLOPT_VERBOSE => true, // Verbose output
CURLOPT_BUFFERSIZE => 10485760, // receive buffer size 3 MB = 3145728 Bytes (in binary) 10 MB = 10485760 Bytes (in binary)
// CURLOPT_WRITEDATA => $ch, // Not supported by PHP
// CURLOPT_FILE => $fileHandle,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_FAILONERROR => true,
CURLOPT_FORBID_REUSE => true,
CURLOPT_FRESH_CONNECT => true,
// CURLOPT_PUT => true, // Not appropriate for the case
CURLOPT_HEADERFUNCTION => $callbackHeader, //
CURLOPT_INFILE => $fR, // CallBack
CURLOPT_INFILESIZE => mb_strlen('HeartBeat', '8bit'), // size
CURLOPT_READFUNCTION => $callbackRead, // CallBack read
CURLOPT_WRITEFUNCTION => $callback, // CallBack write
]);
echo PHP_EOL . 'Set cURL options' . PHP_EOL; var_dump($rO); PHP_EOL;
echo 'Exec...START' . PHP_EOL;
// Execute cURL request
$response = curl_exec($ch);
echo 'Exec...END' . PHP_EOL;
// Check for errors
if ($response === false) {
echo 'cURL error [#' . curl_errno($ch) . ']: ' . curl_error($ch);
} else {
// Output response
echo 'Response: ' . $response;
}
// Close cURL handle
curl_close($ch);
fclose($fileHandle);
rewind($fR);
$tmlFile = stream_get_contents($fR);
fclose($fR);
$jTxt = json_decode($objThis->result);
$jP = json_encode($jTxt, JSON_PRETTY_PRINT);
file_put_contents($outputJsonFile, $jP);
echo PHP_EOL . 'readCalls: ' . $objThis->readCalls . PHP_EOL;
echo PHP_EOL . '$tmlFile: ' . $tmlFile . PHP_EOL;
echo PHP_EOL . 'result: ' . $jP . PHP_EOL;
die('.....................');
I tried to set message result listener and I was expecting to be able to receive/send messages to both directions.
PhpWebDev is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.