i've seen other people with this problem, but maybe i can explain my situation and you can point out where the issue might be.
im getting a 'Warning : socket_bind(): unable to bind address [98]: Address already in use' error.
the situation is this. I am using a web application to trigger another program to perform tasks (from a webpage interface). The results of that program are sent through a socket to my web application that is listening on a socket.
first i create and open the socket, then i trigger the other program, then when that program is finished it should send its results back through the socket.
it works fine the first try. Then the next try (i trigger this process many times) i get the above socket bind error when trying to open the socket, obviously the socket is still bound.
i wait about a minute and i can successfully run the process again. I think the socket connection timesout.
I dont know if the problem is because of the way i have structure my socket code, or if the problem is in the external program that i am triggering. I dont know much about the internals of the external program as its a jar file built by someone else.
heres the code i use for creating and handling the socket. I just used an example on php.net and altered it for my needs.
$port1 = 15000;
// configure the socket
error_reporting(E_ALL);
set_time_limit(0);
ob_implicit_flush();
$address = '127.0.0.1';
$port2 = 54321;
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$error = 'none';
if ($sock) {
if (socket_bind($sock, $address, $port2)) {
if (socket_listen($sock, 5)) {
// trigger external process
if (start_calibration()) {
$buf = array();
// listen to the socket for incoming messages
do {
// if incomming connection is not accepted break out and close socket
if (($msgsock = socket_accept($sock)) === false) {
break;
}
do {
// if cant read socket then break out and close socket
if (false === ($buf = socket_read($msgsock, 2048, PHP_BINARY_READ))) {
break 2;
}
$buf = unpack('C*', $buf);
socket_close($msgsock);
break 2;
} while (true);
socket_close($msgsock);
} while (true);
socket_close($sock);
// code to handle data recieved through the socket
}
else {
// start_calibration failed
$error = 'start_calibration failed';
socket_close($sock);
}
}
else {
// socket_listen failed
$error = 'socket_listen failed';
socket_close($sock);
}
}
else {
// socket_bind failed
$error = 'socket_bind failed';
socket_close($sock);
}
}
else {
// socket_create failed
$error = 'socket_create failed';
}
$data['error'] = $error;
echo json_encode($data);
also, is there is a more efficient way to handle the closing of sockets if there is problems with lines like 'socket_bind', 'socket_listen' etc?
Did you try to set the flag SO_REUSEADDR on your socket?
There's a sample in the socket_set_option's documentation.
Related
My goal is capture messages being generated in real time by a Java server socket and display these messages on the webpage.
I am trying to use php to connect to the socket and receive data from the server. The php client should continuously listen to the server for messages.
Here is my php code
<?php
set_time_limit(0);
$serverAddress=SERVER_ADDRESS;
$serverListeningPort=SERVER_PORT;
//make a connection and get a socket object
if ( ($socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === FALSE )
{
echo "socket_create() failed: reason: " .socket_strerror(socket_last_error());
}
else
{
echo("socket create was successful");
echo("<br>");
}
echo ("Attempting to connect to host");
echo("<br>");
if ( ($result = socket_connect($socket, $serverAddress, $serverListeningPort)) === FALSE )
{
echo ("socket_connect() failed. Reason:".socket_strerror(socket_last_error($socket)));
}
echo ("Reading response:");
$message="";
while(true)//listen for ever
{
$message=socket_read($socket, 300);
if($message!=='')
{
print_r($message);
}
}
?>
When I load this php page, most of the time I get a 504 gateway time out error. I have verified that the Java server is picking up the client connection.
Sometimes, I get a few messages only and then the page stops getting messages from the server. Not sure why, as I have a while(true) loop.
Am I using the php socket correctly? How can I accomplish my goal.
Thank you
Try adding the below lines at the start of your code. This will output the result to browser as it is generated.
ob_end_flush();
ob_implicit_flush(1);
I use socket_create() to create socket Resource,then I bind an IP address to it by socket_bind(), its works fine;
But after a while(more than 30 minutes) in line socket_read($sock, 2048) this error thrown :
"PHP Warning: socket_read(): unable to read from socket [104]: Connection reset by peer in test.php on line 198".
This is my simplified code:
$this->sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
// check if tcp socket ceated or not
if ($this->sock === false) {
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Couldn't create socket: [$errorcode] $errormsg");
}
// Bind the source address
socket_bind($this->sock, $this->ip);
// Connect to destination address
socket_connect($this->sock, $this->mxHost, $this->port);
$buf = socket_read($this->sock, 2048);
This piece of code make a SMTP(port 25) connection to a MX Host at the other side.
Maybe it's the fault on the other side of your connection, But how can I detect that the other side isn't ready for the connection right now. In the other word how can I find out the "Connection reset by peer" occurred?
You should check if socket_connect() was successful before reading from it.
so you could rewrite your code like this:
-- UPDATED --
$this->sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
// Bind the source address
socket_bind($this->sock, $this->ip);
// Connect to destination address
if (socket_connect($this->sock, $this->mxHost, $this->port)) {
// suppress the warning for now since we have error checking below
$buf = #socket_read($this->sock, 2048);
// socket_read() returns a zero length string ("") when there is no more data to read.
// This indicates that the socket is closed on the other side.
if ($buf === '')
{
throw new \Exception('Connection reset by peer');
}
} else {
// Connection was not successful. Get the last error and throw an exception
$errorMessage = socket_strerror(socket_last_error());
throw new \Exception($errorMessage);
}
Hmm... Your peer reset the connection. Maybe it's the fault on the other side of your connection ? A timeout mechanism may be running on the other side.
You could test the socket before you write to it with the socket_last_error function and recreate the connection on a disconnection.
I have socket handler class, which is used to communicate to client with specific ip and port with the help of several socket functions. At the very first time when I am using writetosocket() function, it's working perfectly.
But when I am restarting client(with ip and port). And tries to use writetosocket() it returns me broken pipe error with error code 32. but after some successful execution of socket_write function. Means I am getting this error after some time duration, when I am writing data on socket. I read some solutions and tried most common solution where I am using socket_shutdown and socket_close to terminate socket connection properly whenever I am finding client is not responding. And after that I am again calling startconnection, which is giving me new socket. But still I am getting broken pipe error.
function startconnection(){
/* Create a socket in the AF_INET family, using SOCK_STREAM for TCP connection */
$this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($this->socket === false) {
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
echo "$errorcode : $errormsg";
return false;
}
else {
echo "Socket successfully created.";
}
/* Accept incoming connections */
$this->result = socket_connect($this->socket, $this->ipaddress, $this->port);
if($this->result === false){
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
echo "$errorcode : $errormsg";
return false;
}
else {
echo "successfully connected to $this->ipaddress, $this->port";
}
return true;
}
function writetosocket($input){
$sent = socket_write($this->socket, $input, strlen($input));
if($sent === false) {
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
echo "$errorcode : $errormsg";
return false;
}
else {
echo "Message Sent : $input";
}
return true;
}
Help me to understand and resolve this problem so that function can handle broken pipe error.
You are getting that error because the server socket has closed and is no longer listening and the client socket is attempting to send data to the server socket after it has been closed but before the port is free to be used again (while it is in TIME_WAIT).
The Server Socket and the Client Socket both go through different steps before they become available for I/O:
SERVER
socket()
bind()
listen()
accept()
Client
socket()
bind() [optional, see below]
connect() [does an implicit bind on an ephemeral port if not already bound]
So I've been able to use AJAX to repeatedly refresh a div on my website, using the following code:
var $container = $("#content");
var refreshId = setInterval(function()
{
$container.load('toad.php').fadeOut("slow").load('response.php').fadeIn("slow"); ;
}, 2000);
This works fine, toad.php gets executed every 2 seconds and the contents update.
toad.php contains the following code currently:
<?php
if ( !($sock = socket_create(AF_INET, SOCK_STREAM, 0)) ) {
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Couldn't create socket: [$errorcode] $errormsg \n");
}
echo "Socket created \n";
if (!socket_connect($sock, '127.0.0.1', 45000)) {
//$errorcode = socket_last_error();
//$errormsg = socket_strerror($errorcode);
echo "No sensor available to connect to.\n";
//die("Could not connect: [$errorcode] $errormsg \n");
}
echo "Connection established \n";
//Now receive reply from server
if (false !== ($bytes = socket_recv($sock, $buf, 1200, MSG_WAITALL))) {
echo "Read $bytes bytes from socket_recv(). Closing socket...";
}
else {
echo "socket_recv() failed; reason: " . socket_strerror(socket_last_error($sock)) . "\n";
}
socket_close($sock);
echo $buf . "\n";
echo "OK.\n";
?>
The issue with this is that the socket is created and connected to every single time the div is refreshed.
If I don't have the socket_create and socket_connect functions in toad.php then the socket_recv function doesn't know about the socket and doesn't work.
My question is how can I get the socket receive code to loop and update the contents of the div without having to re create and connect to the socket every time?
Thanks!
If you can rewrite the server your connecting to to use websocket, you could just connect directly from the browser using socket.io.
http://socket.io/
As others have said, maintaining a persistent PHP connection can be tricky, but if running a NodeJS (or similar) script to handle client connections isn't possible you could serve the websockets from that same PHP script.
Try this approach:
http://devzone.zend.com/209/writing-socket-servers-in-php/
Your toad.php script would run on the command line, listening to your existing socket server, then serving the data to it's own socket server which the browser connects to directly with websocket.
I created a PHP Socket Server with PHP_NORMAL_READ mode. So, a message to the server is read when it ends with \n or \r. I tried it by connecting to the server with multiple telnet instances, and it works great.
However, when I connect to the server with 1 flash application and 1 telnet application (I first start the flash one), the flash one seems to make the server hang - the server is getting stuck somewhere and no longer receiving data from eg. the telnet client.
Because anyone can code a flash client, this has to be fixed server side. The server's code:
<?php
// config
$timelimit = 60; // amount of seconds the server should run for, 0 = run indefintely
$port = 9000; // the port to listen on
$address = $_SERVER['SERVER_ADDR']; // the server's external IP
$backlog = SOMAXCONN; // the maximum of backlog incoming connections that will be queued for processing
// configure custom PHP settings
error_reporting(1); // report all errors
ini_set('display_errors', 1); // display all errors
set_time_limit($timelimit); // timeout after x seconds
ob_implicit_flush(); // results in a flush operation after every output call
//create master IPv4 based TCP socket
if (!($master = socket_create(AF_INET, SOCK_STREAM, SOL_TCP))) die("Could not create master socket, error: ".socket_strerror(socket_last_error()));
// set socket options (local addresses can be reused)
if (!socket_set_option($master, SOL_SOCKET, SO_REUSEADDR, 1)) die("Could not set socket options, error: ".socket_strerror(socket_last_error()));
// bind to socket server
if (!socket_bind($master, $address, $port)) die("Could not bind to socket server, error: ".socket_strerror(socket_last_error()));
// start listening
if (!socket_listen($master, $backlog)) die("Could not start listening to socket, error: ".socket_strerror(socket_last_error()));
//display startup information
echo "[".date('Y-m-d H:i:s')."] SERVER CREATED (MAXCONN: ".SOMAXCONN.").\n"; //max connections is a kernel variable and can be adjusted with sysctl
echo "[".date('Y-m-d H:i:s')."] Listening on ".$address.":".$port.".\n";
$time = time(); //set startup timestamp
// init read sockets array
$read_sockets = array($master);
// continuously handle incoming socket messages, or close if time limit has been reached
while ((!$timelimit) or (time() - $time < $timelimit)) {
$changed_sockets = $read_sockets;
socket_select($changed_sockets, $write = null, $except = null, null);
foreach($changed_sockets as $socket) {
if ($socket == $master) {
if (($client = socket_accept($master)) < 0) {
continue;
} else {
array_push($read_sockets, $client);
}
} else {
$data = #socket_read($socket, 1024, PHP_NORMAL_READ); //read a maximum of 1024 bytes until a new line has been sent
if ($data === false) { //the client disconnected
$index = array_search($socket, $read_sockets);
unset($read_sockets[$index]);
socket_close($socket);
} elseif ($data = trim($data)) { //remove whitespace and continue only if the message is not empty
echo "we received: ".$data."\n\n";
//handleData($data, $socket);
}
}
}
}
socket_close($master); //close the socket
echo "[".date('Y-m-d H:i:s')."] SERVER CLOSED.\n";
//function to write to the flash client
function flash_write($socket, $msg) {
socket_write($socket, $msg.chr(0x0));
}
?>
Does anyone know what may cause this? I tried changing the timeout on the socket_select from none to 0 (instant return), but that didn't seem to change anything.
Could you post the source of the flash client? That would show what the problem is?
Are you sure the last thing you send from the flash client is a \n ?
Otherwise the server would block on socket_read() as the flash client socket can be read without blocking (triggered socket_select()), but doesn't send the ending \n.
One thing to help you debug: error_reporting(1) does not enable the display of all errors. Look at the documentation at http://us3.php.net/manual/en/function.error-reporting.php. You need something like error_reporting(E_ALL).