I developed a simple program using PhP websocket that works completely fine on localhost, however when I upload it to server the connection is not established.
I contacted the hosting team and they said there is a problem with the code.
Server
<?php
define('HOST_NAME',"****.com");
define('PORT',"8080");
$null = NULL;
require_once("class.chathandler.php");
$Handler = new Handler();
$socketResource = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socketResource, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($socketResource, 0, PORT);
socket_listen($socketResource);
// $socketResource = socket_create(AF_INET, SOCK_STREAM, 0);
// socket_set_option($socketResource, SOL_SOCKET, SO_REUSEADDR, 1);
// socket_bind($socketResource, HOST_NAME, 0) or die("Could not bind to socket\n");
// socket_listen($socketResource);
$clientSocketArray = array($socketResource);
while (true) {
$newSocketArray = $clientSocketArray;
socket_select($newSocketArray, $null, $null, 0, 10);
if (in_array($socketResource, $newSocketArray)) {
$newSocket = socket_accept($socketResource);
$clientSocketArray[] = $newSocket;
$header = socket_read($newSocket, 1024);
$Handler->doHandshake($header, $newSocket, HOST_NAME, PORT);
socket_getpeername($newSocket, $client_ip_address);
$connectionACK = $Handler->newConnectionACK($client_ip_address);
$Handler->send($connectionACK);
$newSocketIndex = array_search($socketResource, $newSocketArray);
unset($newSocketArray[$newSocketIndex]);
}
foreach ($newSocketArray as $newSocketArrayResource) {
while(socket_recv($newSocketArrayResource, $socketData, 1024, 0) >= 1){
$socketMessage = $Handler->unseal($socketData);
$messageObj = json_decode($socketMessage);
$message = $Handler->createMessage($messageObj->id,$messageObj->message, $messageObj->value);
$Handler->send($message);
break 2;
}
$socketData = @socket_read($newSocketArrayResource, 1024, PHP_NORMAL_READ);
if ($socketData === false) {
socket_getpeername($newSocketArrayResource, $client_ip_address);
$connectionACK = $Handler->connectionDisconnectACK($client_ip_address);
$Handler->send($connectionACK);
$newSocketIndex = array_search($newSocketArrayResource, $clientSocketArray);
unset($clientSocketArray[$newSocketIndex]);
}
}
}
socket_close($socketResource);
Handler
<?php
class Handler {
function send($message) {
global $clientSocketArray;
$messageLength = strlen($message);
foreach($clientSocketArray as $clientSocket)
{
@socket_write($clientSocket,$message,$messageLength);
}
return true;
}
function unseal($socketData) {
$length = ord($socketData[1]) & 127;
if($length == 126) {
$masks = substr($socketData, 4, 4);
$data = substr($socketData, 8);
}
elseif($length == 127) {
$masks = substr($socketData, 10, 4);
$data = substr($socketData, 14);
}
else {
$masks = substr($socketData, 2, 4);
$data = substr($socketData, 6);
}
$socketData = "";
for ($i = 0; $i < strlen($data); ++$i) {
$socketData .= $data[$i] ^ $masks[$i%4];
}
return $socketData;
}
function seal($socketData) {
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($socketData);
if($length <= 125)
$header = pack('CC', $b1, $length);
elseif($length > 125 && $length < 65536)
$header = pack('CCn', $b1, 126, $length);
elseif($length >= 65536)
$header = pack('CCNN', $b1, 127, $length);
return $header.$socketData;
}
function doHandshake($received_header,$client_socket_resource, $host_name, $port) {
$headers = array();
$lines = preg_split("/\r\n/", $received_header);
foreach($lines as $line)
{
$line = chop($line);
if(preg_match('/\A(\S+): (.*)\z/', $line, $matches))
{
$headers[$matches[1]] = $matches[2];
}
}
$secKey = $headers['Sec-WebSocket-Key'];
$secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
$buffer = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"WebSocket-Origin: $host_name\r\n" .
"WebSocket-Location: ws://$host_name:$port/demo/shout.php\r\n".
"Sec-WebSocket-Accept:$secAccept\r\n\r\n";
socket_write($client_socket_resource,$buffer,strlen($buffer));
}
function newConnectionACK($client_ip_address) {
$message = 'New client ' . $client_ip_address.' joined';
$messageArray = array('message'=>$message,'message_type'=>'connection-ack');
$ACK = $this->seal(json_encode($messageArray));
return $ACK;
}
function connectionDisconnectACK($client_ip_address) {
$message = 'Client ' . $client_ip_address.' disconnected';
$messageArray = array('message'=>$message,'message_type'=>'connection-ack');
$ACK = $this->seal(json_encode($messageArray));
return $ACK;
}
function createMessage($id,$message,$value) {
$messageArray = array('id'=>$id,'message'=>$message,'value'=>$value);
$TheMessage = $this->seal(json_encode($messageArray));
return $TheMessage;
}
}
?>
Client
var websocket = new WebSocket("wss://*****.com:8080/PATH/server.php");
Locally I run
php -q server.php
or in the index I write
$lastLine = shell_exec("php q- server.php");
and it works perfectly both ways.
I tried to execute the server file on web server and it didn't work. I logged in to my account via ssh and I tried to run the file from command line using
php -q server.php
or
nohup server.php
Both didn't work
Strace
bind(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("0.0.0.0")}, 16) = -1 EACCES (Permission denied)
select(4, [3], [], [], {0, 10}) = 0 (Timeout)
After change the server code to
<?php
define('HOST_NAME',"*****.com");
$null = NULL;
require_once("class.chathandler.php");
$Handler = new Handler();
$socketResource = socket_create(AF_INET, SOCK_STREAM, 0);
socket_set_option($socketResource, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($socketResource, HOST_NAME, 0) or die("Could not bind to socket\n");
socket_listen($socketResource);
the result of strace:
Process 28975 attached
restart_syscall(<... resuming interrupted call ...>) = 0
fcntl(3, F_SETLKW, {type=F_WRLCK, whence=SEEK_SET, start=0, len=1}) = 0
fcntl(3, F_SETLK, {type=F_UNLCK, whence=SEEK_SET, start=0, len=1}) = 0
lstat("/home/customer/www/****-****.com/public_html/***/./class.chathandler.php", {st_mode=S_IFREG|0644, st_size=2640, ...}) = 0
lstat("/home/customer/www/***-****.com/public_html/***/class.chathandler.php", {st_mode=S_IFREG|0644, st_size=2640, ...}) = 0
openat(AT_FDCWD, "/home/customer/www/***-***.com/public_html/****/class.chathandler.php", O_RDONLY) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=2640, ...}) = 0
openat(AT_FDCWD, "/home/customer/www/****-***.com/public_html/*****/class.chathandler.php", O_RDONLY) = 5
fstat(5, {st_mode=S_IFREG|0644, st_size=2640, ...}) = 0
mmap(NULL, 2640, PROT_READ, MAP_SHARED, 5, 0) = 0x7fa918f2a000
munmap(0x7fa918f2a000, 2640) = 0
close(5) = 0
openat(AT_FDCWD, "/home/customer/.opcache/7.4.20-Jun 8 2021-07:38:48-7a502f21e059df70a79cf689ceb05dd9/home/customer/www/****-****.com/public_html/****/class.chathandler.php.bin", O_RDONLY) = 5
flock(5, LOCK_SH) = 0
read(5, "OPCACHE\0007a502f21e059df70a79cf689"..., 80) = 80
read(5, "\30\2\0\0\0\0\0\0\2\0\0\0\0\0@\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 14720) = 14720
flock(5, LOCK_UN) = 0
close(5) = 0
fcntl(3, F_SETLKW, {type=F_WRLCK, whence=SEEK_SET, start=0, len=1}) = 0
fcntl(3, F_SETLK, {type=F_UNLCK, whence=SEEK_SET, start=0, len=1}) = 0
close(4) = 0
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 4
setsockopt(4, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
stat("/etc/resolv.conf", {st_mode=S_IFREG|0644, st_size=59, ...}) = 0
openat(AT_FDCWD, "/etc/hosts", O_RDONLY|O_CLOEXEC) = 5
lseek(5, 0, SEEK_CUR) = 0
fstat(5, {st_mode=S_IFREG|0644, st_size=105, ...}) = 0
read(5, "127.0.0.1 localhost c25459 c2545"..., 4096) = 105
lseek(5, 0, SEEK_CUR) = 105
read(5, "", 4096) = 0
close(5) = 0
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 5
fstat(5, {st_mode=S_IFREG|0644, st_size=44304, ...}) = 0
mmap(NULL, 44304, PROT_READ, MAP_PRIVATE, 5, 0) = 0x7fa918ef5000
close(5) = 0
openat(AT_FDCWD, "/lib64/libnss_dns.so.2", O_RDONLY|O_CLOEXEC) = 5
read(5, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P#\0\0\0\0\0\0"..., 832) = 832
fstat(5, {st_mode=S_IFREG|0755, st_size=39016, ...}) = 0
mmap(NULL, 32776, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 5, 0) = 0x7fa914fa0000
mmap(0x7fa914fa2000, 16384, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 5, 0x2000) = 0x7fa914fa2000
mmap(0x7fa914fa6000, 4096, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 5, 0x6000) = 0x7fa914fa6000
mmap(0x7fa914fa7000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 5, 0x6000) = 0x7fa914fa7000
mmap(0x7fa914fa8000, 8, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fa914fa8000
close(5) = 0
mprotect(0x7fa914fa7000, 4096, PROT_READ) = 0
munmap(0x7fa918ef5000, 44304) = 0
socket(PF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 5
setsockopt(5, SOL_IP, IP_RECVERR, [1], 4) = 0
connect(5, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
poll([{fd=5, events=POLLOUT}], 1, 0) = 1 ([{fd=5, revents=POLLOUT}])
sendto(5, "\331N\1\0\0\1\0\0\0\0\0\0\***-****\3com\0"..., 36, MSG_NOSIGNAL, NULL, 0) = 36
poll([{fd=5, events=POLLIN}], 1, 5000) = 1 ([{fd=5, revents=POLLIN}])
ioctl(5, FIONREAD, [52]) = 0
recvfrom(5, "\331N\205\200\0\1\0\1\0\0\0\0\****-***\3com\0"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, [16]) = 52
close(5) = 0
bind(4, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("35.206.107.63")}, 16) = 0
listen(4, 0) = 0
select(5, [4], [], [], {0, 10}) = 0 (Timeout)