Can PHP asynchronously use sockets?
Yup, that's what socket_set_nonblock()
is for. Your socket interaction code will need to be written differently, taking into account the special meanings that error codes 11, EWOULDBLOCK
, and 115, EINPROGRESS
, assume.
Here's some somewhat-fictionalized sample code from a PHP sync socket polling loop, as requested:
$buf = '';
$done = false;
do {
$chunk = socket_read($sock, 4096);
if($chunk === false) {
$error = socket_last_error($sock);
if($error != 11 && $error != 115) {
my_error_handler(socket_strerror($error), $error);
$done = true;
}
break;
} elseif($chunk == '') {
$done = true;
break;
} else {
$buf .= $chunk;
}
} while(true);
Open asynchronous sockets in PHP
Use different functions: socket_create()
and socket_connect()
instead of fsockopen()
. This works:
$socks = array();
for ($port = 21; $port <= 25; $port++) {
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_nonblock($sock);
@socket_connect($sock, 'localhost', $port);
$socks[$port] = $sock;
}
$startTime = microtime(true);
while ($socks && microtime(true) - $startTime < 3) {
$null = null;
$write = $socks;
socket_select($null, $write, $null, 1);
foreach ($write as $port => $sock) {
$desc = "$port/tcp";
$errno = socket_get_option($sock, SOL_SOCKET, SO_ERROR);
if ($errno == 0) {
echo "$desc open\n";
} elseif ($errno == SOCKET_ECONNREFUSED) {
echo "$desc closed\n";
} elseif ($errno == SOCKET_ETIMEDOUT) {
echo "$desc filtered\n";
} else {
$errmsg = socket_strerror($errno);
echo "$desc error $errmsg\n";
}
unset($socks[$port]);
socket_close($sock);
}
}
foreach ($socks as $port => $sock) {
$desc = "$port/tcp";
echo "$desc filtered\n";
socket_close($sock);
}
How to make asynchronous HTTP requests in PHP
The answer I'd previously accepted didn't work. It still waited for responses. This does work though, taken from How do I make an asynchronous GET request in PHP?
function post_without_wait($url, $params)
{
foreach ($params as $key => &$val) {
if (is_array($val)) $val = implode(',', $val);
$post_params[] = $key.'='.urlencode($val);
}
$post_string = implode('&', $post_params);
$parts=parse_url($url);
$fp = fsockopen($parts['host'],
isset($parts['port'])?$parts['port']:80,
$errno, $errstr, 30);
$out = "POST ".$parts['path']." HTTP/1.1\r\n";
$out.= "Host: ".$parts['host']."\r\n";
$out.= "Content-Type: application/x-www-form-urlencoded\r\n";
$out.= "Content-Length: ".strlen($post_string)."\r\n";
$out.= "Connection: Close\r\n\r\n";
if (isset($post_string)) $out.= $post_string;
fwrite($fp, $out);
fclose($fp);
}
Starting Pure PHP socket in Backend/Asynchronously
Solved this, it is not the one that i really want to do, but it's working now properly like what i intended to do from the first place..
Here is how i looks now:
public function __socket_write($text)
{
$service_port = xxxxxx;
$address = MyAddress;
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$result = socket_connect($socket, $address, $service_port);
if ($result === false)
{
$this->__socket_start();
}
@socket_listen($socket);
...
socket_close($socket);
}
public function __socket_start()
{
$cmd = "php server.php";
shell_exec($cmd." > /dev/null 2>/dev/null &");
}
Is there a way to listen for new socket connections while doing a do, while loop in PHP?
I found the solution.
To anyone who was wondering what it was, use:
socket_set_nonblock($socketservervariable);
to make the server not wait for a client to connect before proceeding. That creates a new error though. When doing the client handshake the socket_read wanted a socket but it got the boolean value of false when the socket_accept function didn't detect a client connecting. So this was my solution to that:
$newclient = socket_accept($server);
if($newclient != false){
handshake($server, $newclient);
$clients[count($clients)] = $newclient;
echo "\n\nNew client connected!\n\n";
}
and that solved all of my problems.
How to implement a high performance asynchronous socket server application in PHP?
I think this is a typical case of "If all you have is a hammer, everything looks like a nail."
As you yourself already figured out, php is not the right tool for the job. You can probably find a way to do it anyway, but it'll most likely be messy.
So use the right tool for the job. You would not use a hammer to drive a screw into the wall, would you?
Related Topics
PHP E-Mail Form Sender Name Instead of E-Mail
How to Change the Array Key to Start from 1 Instead of 0
How to Find Annotations in a PHP5 Object
Change Database Connection in Laravel Model
How to Loop Through JSON Array
Mp4 Plays When Accessed Directly, But Not When Read Through PHP, on iOS
Split an Array into N Arrays - PHP
How to Print Multidimensional Arrays in PHP
How to Execute a Shell Script in PHP
iOS Push Notification Does Not Work When Using Crontab Scheduler
Query MySQL and Export Data as CSV in PHP