fsockopen not working? - php

I am trying to connect to an IRC server via PHP on a command line using Windows 7.
Everytime when running this:
$socket = fsockopen($irc_server, 6667, $errno, $errstr, 5);
$errno = 0, $errstr = "" and $socket = 'Resource id #4' (using die($socket);)
What is the cause of this, and how can I debug more into this.
The following code:
$s = fsockopen("google.com", 80, $errno, $errstr, 5);
die($errno.", ".$errstr.", ".$s);
...returns the following:
0, , Resource id #4
I can't use $socket. It says "Invalid resource" when I try to use it. Also, the PHP documentation notes that errno 0 indicates a wrongly opened socket.
Help is appreciated.

Could you show us a little more of your code?
What happens with this code:
$s = fsockopen($irc_server, 6667, $errno, $errstr, 5);
if ($s === false) {
die($errno.", ".$errstr.", ".$s);
} else {
// your code with socket
die("Valid socket resource");
}
?

I fixed it.
function irCmd didn't know $socket, so I put this in front of it:
global $socket;
And it worked. Thanks a bunch!

The documentation says (emphasis mine):
If the value returned in errno is 0 and the function returned FALSE, it is an indication that the error occurred before the connect() call. This is most likely due to a problem initializing the socket.
Since the function did not return false, the socket is valid. If you are having further problems, tells us what they are; fsockopen has returned normally here.

Related

PHP Socket Server Hangs

I've worked hours and hours on this, and I can't figure it out. I've browsed the posts on here trying to find the solution also and to no avail.
I have a Socket Server setup for my browser-based game. I've stripped it down trying to find the issue, and it seems that fread is hanging because if I comment out "fread($fp, 10024);" then it runs fine, but of course doesn't read the response.
While I debug this, I've broken the files down to the basics.
I have the Socket Server: ChatServer.php
set_time_limit(0);
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_get_option($sock, SOL_SOCKET, SO_REUSEADDR);
socket_bind($sock, "127.0.0.1", "9990");
socket_listen($sock, 4);
$chatContent = "Testing, 1, 2, 3.";
do
{
$childSocket = socket_accept($sock);
$incomingData = socket_read($childSocket, 12048);
socket_write($childSocket, $chatContent, strlen($chatContent));
} while(true);
Then I have Test.php which should open the socket and read a response.
$fp = fsockopen("127.0.0.1", "9990", $errno, $errstr, 5);
echo $errstr . "<br />";
echo fread($fp, 10024);
$errstr doesn't display an error, because when I start ChatServer.php then reload Test.php, it never reloads. It hangs for minutes and lags my entire server. I'm running on a VPS. This worked fine before, then suddenly stopped working, and I can't figure out why.
Edit: Thanks to GigaWatt, I was able to get it working. Here is the code I used if you have the same issue. :)
set_time_limit(0);
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_get_option($sock, SOL_SOCKET, SO_REUSEADDR);
socket_bind($sock, "127.0.0.1", "9990");
socket_listen($sock, 4);
$chatContent = "Testing, 1, 2, 3.";
do
{
$childSocket = socket_accept($sock);
$meta = stream_get_meta_data($sock);
if($meta['unread_bytes'] > 0) {
$incomingData = socket_read($childSocket, $meta['unread_bytes']);
}
socket_write($childSocket, $chatContent, strlen($chatContent));
} while(true);
Just use stream_get_meta_data and then unread_bytes.
The call to socket_read is a blocking call, meaning everything stops until the specified number of bytes have been read.
If you need to continue processing, consider using stream_get_meta_data (the unread_bytes value) to check how much unread data is waiting.
Once it reaches the desired threshold, then call socket_read.
http://us3.php.net/manual/en/function.stream-get-meta-data.php
It does exactly what you tell it to: waits for 12048 / 10024 bytes of data or socket being closed.
You might be interested in using a non-blocking socket (socket_set_nonblock/stream_set_blocking) and a socket_select loop or libevent.

PHP socket_accept throws warnings in non-blocking mode

I want to create an easy PHP server (TCP-based) that would serve actual time and close the connection immediately. I've done that already. I wanted to add crtl-C handling so I needed to replace blocking socket_accept with non-blocking (this is because when the blocking socket_accept instruction is reached and I send SIGINT /ctrl-C/ then the server will still be alive until the first client is server and then it closes itself - and I didn't want this behavior).
My current code looks like this:
<?php
error_reporting(E_ALL);
ob_implicit_flush();
if ($argc != 2)
die("Wrong params");
$address = 'localhost';
$port = $argv[1];
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false)
die(socket_strerror(socket_last_error()) . "\n");
if (socket_bind($sock, $address, $port) === false)
die(socket_strerror(socket_last_error($sock)) . "\n");
if (socket_listen($sock, 5) === false)
die(socket_strerror(socket_last_error($sock)) . "\n");
socket_set_nonblock($sock);
$remote_host = $remote_port = $msgsock = null;
declare(ticks = 1);
function sig_handler($signo)
{
switch ($signo) {
case SIGTERM:
case SIGINT:
global $sock;
socket_shutdown($sock);
socket_close($sock);
echo "Terminating...\n";
exit;
}
}
pcntl_signal(SIGTERM, "sig_handler");
pcntl_signal(SIGINT, "sig_handler");
echo "Starting server\n";
while (1) {
do {
$msgsock = socket_accept($sock);
usleep(100000);
} while ($msgsock === false);
socket_getpeername($msgsock, $remote_host, $remote_port);
echo "Connection made from {$remote_host}:{$remote_port}\n";
$msg = date('r', time()) . "\n";
socket_write($msgsock, $msg, strlen($msg));
socket_close($msgsock);
};
socket_close($sock);
Everything works fine except for one detail... I get the following PHP warning every 0.1 second (= 100000 microseconds):
PHP Warning: socket_accept(): unable to accept incoming connection [11]: Resource temporarily unavailable in /home/tomasz/Development/Python/twisted/time-server.php on line 55
PHP Stack trace:
PHP 1. {main}() /home/tomasz/Development/Python/twisted/time-server.php:0
PHP 2. socket_accept() /home/tomasz/Development/Python/twisted/time-server.php:55
What I've tried to achieve is non-blocking accept: PHP uses the server socket, checks if there's any connection awaiting to be served. I not - wait 0.1 second. If there is a pending connection, serve it. All functionality is OK except that I've got no idea why is this warning thrown - I just want to check if there's any connection to be served. Modifying error_reporting to E_ERROR makes the warnings quiet, but I hope there's a better way to solve that...
edit:
modifying socket_accept($sock) to #socket_accept($sock) will just suspress warnings from being thrown, but still this doesn't state why it is thrown...
I located your question while searching for a solution to the exact same problem. Additionally, I found a few other posts asking about the same thing, but also without solutions. Some posts indicated that there was no way to prevent socket_accept() from throwing warnings, as it is by design to indicate "there is no waiting connection to accept." I couldn't confirm this as it doesn't seem to be mentioned in the PHP manual page for socket_accept()
Like you, I wasn't satisfied with using any sort of error suppression. It seemed the next logical step was to wrap socket_accept() in some sort of conditional so that it would only execute if I knew there was a connection waiting. I couldn't find anything that did this. But when using stream_*() functions instead of just socket_*() functions, it looks like there is. So I switched out to using streams (seems there are some other advantages as well), as follows:
if (( $socket = stream_socket_server( "tcp://$address:$port", $errno, $errstr )) === FALSE ) {
die( "failed to create socket: $errstr\n" );
}
echo "Waiting for clients to connect...\n";
while ( $server_listening ) {
$read = array( $socket );
$array = array();
if ( stream_select( $read, $array, $array, 0 )) {
$connection = stream_socket_accept( $socket, 0 );
client_handler( $socket, $connection );
} else {
usleep( 100 );
}
}
This seems to work well. My script only attempts to accept the connection if it first determines that there is a connection waiting. After going through this, I did find that there was an equivalent socket function for this, socket_select(), which appears to work the same way. So you may be able to do something similar if you wanted to stick with the socket_*() functions.
On a side note, I'm glad I made the switch to streams as they seem easier to work with. And since my application is limited to TCP, I don't seem to be missing any functionality that I would get with more low-level sockets.
There is something that does that, and it's select(). Nonblocking socket IO should use select(), period. In PHP that means socket_select(). See any reference on BSD sockets for more info.

PHP5 fsockopen connection error break site, no matter how I capture it

I'm trying to use fsockopen to communicate with a game server, which responds with some basic stats. It works perfectly when the server is online, but if the server is ever offline, the following code causes php to stop displaying the page that reads the data.
try {
$socket = fsockopen($host, $port, $errno, $errstr, 10);
if ($socket !== false) {
fwrite($socket, "\xFE");
$data = "";
$data = fread($socket, 1024);
fclose($socket);
if ($data !== false && substr($data, 0, 1) == "\xFF") {
// get into
} else {
// Server did not send back proper data, or reading from socket failed.
print "Server not available.";
}
} else {
// ...
}
} catch(Exception $e){
// ...
}
I've tried the try/catch, I've tried adding a custom handler to the exception. My only idea is to run this outside of the web requests and store the response so that the web request isn't initiating it.
Any thoughts?
First, I'd add a couple of echo commands, either side of the fsockopen call:
echo date("Y-m-d H:i:s")."Before open\n";
$socket = fsockopen($host, $port, $errno, $errstr, 10);
echo date("Y-m-d H:i:s")."After open (socket=".($socket===false?"Bad":"OK")."\n";
This is to confirm the 10 second timeout is working. If you never see the second message then the timeout is not working, and the problem is more obscure.
Anyway, if you are getting a valid $socket, but the lock-up happens later, then try:
if ($socket !== false) {
stream_set_timeout($socket,2); //2 second timeout
stream_set_blocking($socket,false); //no blocking
fwrite($socket, "\xFE");
...
P.S. If adding those two commands solves the problem, then experiment to see if just one of them solves it. That would give a big clue what the real problem is.
It seems that by moving the logic outside the html generation worked. The lookup happens before any html is rendered, so if it fails it doesn't interrupt the html output.

Creating s simple client/server UDP example in PHP

I'm trying to make a simple UDP client server example in PHP but I face an error.
This is the client :
$fp = stream_socket_client("udp://192.168.0.12:12478", $errno, $errstr);
if ($fp)
{
fwrite($fp, "TEST 1 TEST 2 TEST 3");
$buf = fgets($fp);
var_dump($buf);
fclose($fp);
}
This is the server :
$socket = stream_socket_server("udp://192.168.0.12:12478", $errno, $errstr, STREAM_SERVER_BIND);
if ($socket)
{
while ($conn = stream_socket_accept($socket)) {
fwrite($conn, date("D M j H:i:s Y\r\n"));
fclose($conn);
}
fclose($socket);
}
All executions end with :
Warning: stream_socket_accept(): accept failed: Operation not supported
Basically, this is the example given in all PHP documentations but I can't figure what is wrong in it. Any help is greatly appreciated.
Thanks.
Here is the warning on the very same page
Warning
This function should not be used with UDP server sockets. Instead,
use stream_socket_recvfrom() and
stream_socket_sendto().
according to the documentation: "you cannot make a silk piurse from a sow's ear"
stream_socket_connect is intended for STREAMS, not datagram packets. recvfrom would be more likely to work in this scenario.

Why is php's fsockopen returning (Resource temporarily unavailable)?

I have a very simple server php code like this
function listenForClients()
{
$this->serviceConnection = socket_create(AF_UNIX, SOCK_STREAM, 0);
socket_bind($this->serviceConnection, "\tmp\mysock", 0);
socket_listen($this->serviceConnection, 10000000);
while($clientSocket = socket_accept($this->serviceConnection))
{
$clientMessage = socket_read($clientSocket, 1024);
socket_close($clientSocket);
}
}
Then I have a very simple client that does this
for ( $counter = 0; $counter <= 1000; $counter ++) {
$fp = fsockopen("unix///tmp/mysock", 0, $errno, $errstr);
if (!$fp){
echo "Error: Could not open socket connection at " . $counter . "\n";
exit;
}else{
fputs ($fp, "hello", strlen("hello"));
fclose($fp);
}
}
For some reason, after a random number of connections (around 300-500) fsockopen will return with a warning Resource temporarily unavailable. In the beginning I was getting the warning at around 20-30 connections. But once I increased the backlog parameter in socket_listen it got a bit better to around 300-500. How do I overcome this?
What is the way to build a php server socket to accept a lot of incoming connections per second (sustained).
Thanks!
The full error:
PHP Warning: fsockopen(): unable to
connect to unix:///tmp/mysock:0
(Resource temporarily unavailable) in
test.php on line 22
Check your ulimit. Are you overflowing your file descriptor table?
EDIT: the backlog value you have in accept() is bogus. Most OS-es have the max incoming connection queue size on the scale of dozens, not thousands.
I've just been looking at this issue (got here through Google) and I've found that a solution to get rid of the error:
PHP Warning: fsockopen(): unable to connect to unix:///tmp/mysock:0 (Resource temporarily unavailable) in test.php on line 22
..is to not use fsockopen() in the writer thread; try something like this instead:
if (! ($cSock = socket_create(AF_UNIX, SOCK_STREAM, 0))) {
exit("Failed to create socket");
continue;
} else if (! socket_connect($cSock, IPC_SOCK)) {
exit("Failed to connect socket");
} else {
$bw = socket_write($cSock, $msg);
if ($bw === false) {
exit("Socket write failed, %s", array(socket_strerror(socket_last_error())));
} else {
exit("Wrote $bw bytes to socket");
}
}
socket_shutdown($cSock);
socket_close($cSock);
Better late than never ? ;-)

Categories