I am running an apache server on a linux machine.
Im trying to create a website which has a page that needs asynchronous updates and two-way communication with the server.
Im trying to make this simple file which fires up as an intermediate server for each session the code looks something like this:
<?php
$server = stream_socket_server("tcp://localhost:8090", $errno, $errstr);
if(!$server){
echo "$errstr ($errno)<br>";
die();
}
$users = [];
//var_dump($server);
while(true){
$client = stream_socket_accept($server); // new connection
echo "new connection<br>";
array_push($users, $client);
$pid = pcntl_fork();
if($pid){
while(true){
$buff='';
while(!str_ends_with($buff, "\n\r")){
$buff = $buff . fread($client, 1024);
}
//$len = strlen($buff);
foreach($users as $u){ // broadcast
fwrite($u, $buff);
}
if($buff == 'END'){
exit(1);
}
echo "routed<br>";
}
}
}
?>
This is supposed to be a basic echo broadcast. it keeps track of new connections and waits for any client to send a message and sends it back to everyone.
the basic idea was that it would listen for a new connection and use fork to handle the read and write processes.
However I've recently learned that fork() does not work on apache and so my question is how can i make this work.
Related
I'm trying to build a queue system with a FIFO file. This is actually working prety fine on my local development machine. But when I want to deploy to production, I'm running into the issue that my WEB server and CLI server are two seperate servers. And so the fifo file is not working when the listener is started on the CLI server and something is added from the WEB server.
So I need to start the listener from the WEB SAPI, but how can I do that? And also, if it crashes, it needs to be restarted again.
I know how to do this all from just on server, but no idea how to do so on multiple server setup.
The code:
<?php
//queue-listener.php
function process($job) {
sleep(1); //. make it look like we did work.
return;
}
$queue = array();
//////// setup our named pipe ////////
$pipefile = '/storage/queueserver';
umask(0);
if(!file_exists($pipefile)){
if(!posix_mkfifo($pipefile,0666)) {
die('unable to create named pipe');
}
}
$pipe = fopen($pipefile,'r+');
if(!$pipe) die('unable to open the named pipe');
stream_set_blocking($pipe,false);
//////// process the queue ////////
while(1) {
while($input = trim(fgets($pipe))) {
stream_set_blocking($pipe,false);
$queue[] = $input;
}
$job = current($queue);
$jobkey = key($queue);
if($job) {
echo 'processing job ', $job, PHP_EOL;
process($job);
next($queue);
unset($job,$queue[$jobkey]);
} else {
echo 'no jobs to do - waiting...', PHP_EOL;
stream_set_blocking($pipe,true);
}
}
Code for adding something to queue
$pipefile = '/storage/queueserver';
$fhp = fopen($pipefile, 'r+') or die ("can't open file $pipefile");
fwrite($fhp, "GenerateLabel|". date('H:i:s')."\n");
I have a weird issue and I can't seem to find a solution or anything closer to the issue I am having ,
Here is the thing , I have a scoket script run via php on command line, it accepts connection and reads data in json format from mobile app clients and sends appropriate response in json.
Everything works fine except the number of connection does not go above 256 connection.
I would like to know why is that, and how can I solve it ? I have been It on so many days, but no luck!
Here is the script snippet
<?php
date_default_timezone_set("UTC");
$server = stream_socket_server("tcp://192.168.1.77:25003", $errno, $errorMessage);
if (!$server) {
die("$errstr ($errno)");
}
echo "Server started..";
echo "\r\n";
$client_socks = array();
while (true) {
//prepare readable sockets
$read_socks = $client_socks;
$read_socks[] = $server;
//start reading and use a large timeout
if (!stream_select ($read_socks, $write, $except, 10000)) {
die('something went wrong while selecting');
}
//new client
if (in_array($server, $read_socks)) {
$new_client = stream_socket_accept($server);
if ($new_client) {
//print remote client information, ip and port number
echo 'Connection accepted from ' . stream_socket_get_name($new_client, true);
echo "\r\n";
$client_socks[] = $new_client;
echo "Now there are total ". count($client_socks) . " clients";
echo "\r\n";
}
// echo stream_socket_get_name($new_client, true);
//delete the server socket from the read sockets
unset($read_socks[array_search($server, $read_socks)]);
}
$data = '';
$res = '';
//message from existing client
foreach($read_socks as $sock) {
stream_set_timeout($sock, 1000);
while($resp = fread($sock, 25000)) {
$data .= $resp;
if (strpos($data, "\n") !== false) {
break;
}
}
$info = stream_get_meta_data($sock);
if ($info['timed_out']) {
unset($client_socks[array_search($sock, $client_socks)]);
#fclose($sock);
echo 'Connection timed out!';
continue;
}
$client = stream_socket_get_name($sock, true);
if (!$data) {
unset($client_socks[array_search($sock, $client_socks)]);
#fclose($sock);
echo "$client got disconnected";
echo "\r\n";
continue;
}
//send the message back to client
$decode = json_decode($data);
$encode = json_encode($res);
fwrite($sock,$encode."\n");
}
}
P.S.: What I did is, extensive search on the topic, and went over article like these,
http://smallvoid.com/article/winnt-tcpip-max-limit.html and two dozens others.
I have a windows 7 running this thing + wamp 2.5 which runs php 5.5.12
It's nothing to do with your code, it's a "feature" of MS Windows to make you buy the server edition (or upgrade to a different OS). Functionally there's no difference between the server and desktop editions of the NT kernel (some different optimization tweaks) its just a means of ensuring you are complying with the terms of the licence.
I'm looking for solution to read and process message from stream within created socket server.
I've come to this:
$server = stream_socket_server("tcp://0.0.0.0:8000", $errno, $errorMessage);
for (;;)
{
$client = #stream_socket_accept($server);
if ($client)
{
echo 'Connection accepted from '.stream_socket_get_name($client, false) . "n";
stream_copy_to_stream($client, $client);
fclose($client);
}
}
which simply echoes whatever is sent to stream. I cannot find out what do I need to do, say, between stream_socket_accept() and fclose() to get contents of message and act upon it. Any help? Thanks in advance.
I have been trying to make a PHP socket server, something I never done before. So I might not get how all the socket_* functions work.
What I have trouble with is the timeout function in socket_select.
while(true){
//Copy $clients so the list doesn't get modified by socket_select();
$read = $clients;
$write = $clients;
//new socket tries to connect
if(!$new = socket_accept($socket)){
echo "socket_accept() failed: reason: " . socket_strerror(socket_last_error()); break;
}
//Accept the new client
if(!in_array($new, $clients)){
$clients[] = $new;
sendMessage($new, "Hello and welcome to the PHP server!");
}
//Wait for read
socket_select($read, $write, $empty, 5, 5);
foreach($read as $client){
$id = array_search($client,$clients);
echo $id." ".readMessage($client);
}
//Write data to the connected sockets
foreach($write as $client){
sendMessage($client, rand(0,99999));
}
echo "I'm bored\n";
}
From what I understand of socket_select is that this script should say, "I'm bored" every 5 seconds. But it doesn't, why?
Why I want to timeout socket_select is to make a loop so I can send data to the connected sockets.
You're calling socket_accept() every time around the loop. This call will block if no new connections have arrived.
Add $socket to the array of sockets you pass to socket_select(), and only call socket_accept() if that socket shows up as readable. (You'll also need to make that socket an exception in your other loops so that you don't try to write to it.)
I am trying to create a inetd-like service for Windows in PHP for future use with my other application.
So all I can think of is to use Steam Server and proc_open to pipe the stream directly to the process (like inetd). Because on Windows there is no pcntl_fork(), and PHP doesn't support threading.
So far, here is my code. The inetdtest program is a simple program with single printf (written in C). But the problem is that when I connected to my server (via netcat), I got no response message.
<?php
define ('SERVICE_COMMAND', 'inetdtest');
define ('SERVICE_PORT', 35123);
function main() {
echo "Simple inetd starting...\n";
$socket = stream_socket_server('tcp://0.0.0.0:' . SERVICE_PORT, $errno, $errstr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN);
if ($socket === false) {
echo "Can't bind to service port.\n";
echo "[$errno] $errstr";
die(1);
}
$processes = array();
while (true) {
$current = #stream_socket_accept($socket, 5, $host);
if ($current !== false) {
echo 'Incomming connection from client ' . $host . "\n";
echo "Lunching child process... ";
$io = array(
0 => $current,
1 => $current,
2 => array('file', 'stderr.log', 'a')
);
$proc = proc_open(SERVICE_COMMAND, $io, $pipes, NULL, NULL, array('bypass_shell'));
$status = proc_get_status($proc);
echo " DONE! PID : {$status['pid']}\n";
$processes[] = array($current, $proc);
}
foreach ($processes as $k=>$v) {
$status = proc_get_status($v[1]);
if (false === $status['running']) {
echo "Finalizing process {$status['pid']}... ";
fflush($v[0]);
fclose($v[0]);
proc_close($v[1]);
unset($processes[$k]);
echo "DONE!\n";
}
}
}
}
main();
The code justs works as it stands here (using cat as program and on linux), so the problem lies somewhere in the windows side of things.
For one thing, the option you are passing, to bypass the shell, should be given as
array('bypass_shell'=>true)
This may fix things already. The tricky part with these things, is that you're passing a socket fd to a process, which may or may not be expected to handle that properly. I don't know how these things are done in windows, but cutting cmd out of the equation can only help.
If it still doesn't work, you should create a loop which waits for data (either from network or child processes) and sends data from the network socket to the process pipe, and vice versa.