I am trying to make a simple TCP/IP connection to a given IP and Port using sockets in PHP.
I am getting an error message that says "A non-blocking socket operation could not be completed immediately." below is my code:
<?php
$address = 'myhost.com';
$service_port = 1234;
$timeout = 1000;
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_nonblock($socket);
$error = NULL;
$attempts = 0;
while (!($connected = #socket_connect($socket, $address, $service_port)) && ($attempts < $timeout)) {
$error = socket_last_error();
if ($error != SOCKET_EINPROGRESS && $error != SOCKET_EALREADY) {
echo socket_strerror($error) . "\n";
socket_close($socket);
return NULL;
}
usleep(1000);
$attempts++;
}
?>
any ideas? i know there are no issues with the target host ip or port.
You are calling connect() on a non-blocking socket. The connect() call will always need to block to complete its operation, and since you explicitly told the socket to be non-blocking it immediately returns with an error telling you that it did not (yet) complete its operation.
You are a bit at the mercy of the OS you are using when using sockets directly. The code looks good overall. You will retry the connect until you get EINPROGRESS. Is that indeed the error code you are seeing? Maybe you are checking for the wrong error code?
Anyway your code looks to me like you try to connect until the connection is established. You can use blocking mode directly to achieve that.
Just leave the socket as blocking until you connected it and set the socket to non-blocking (assuming you really need that) after it is connected.
non-blocking socket usually used for servers, servers are waiting for connection, so instead of using socket_connect, try using socket_listen instead
if you want to establish a connection to a server (be a client) then use Johannes's suggestion
Related
I have a weighing scale connected to a client pc with a serial port. The client PC is installed with SERPROXY. Using telnet xx.xx.xx.xx port 25003, the data is shown successfully. It means SERPROXY is working fine and port forwarding is done properly in router too. I will share the real public ip upon request to see the data using telnet.
How do I about to read and echo it on the web page ?
The following piece of code fails on binding using sockets?
error_reporting(E_ALL);
// Server IP address
$address = "xx.xx.xx.xx"; // here goes the real public ip address
// Port to listen
$port = 25003;
$mysock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($mysock,$address, $port) or die('Could not bind to address');
socket_listen($mysock, 5);
$client = socket_accept($mysock);
// read 1024 bytes from client
$input = socket_read($client, 1024);
echo $input ;
socket_close($client);
socket_close($mysock);
Its my first time attempt in socket. Does it have to be compulsorily two way communication, ie, for example, server.php and client.php ? Otherwise the sockets don't work.
Is there any other way we can read the output of the said ip address & port in php web page ?
Spent several hours but to no luck. Help would be greatly appreciated.
NOTE: server is hosted on bluehost. socket_extensions are enabled, verified.
EDIT: Also confirmed with bluehost that the port 25003 is open from their side.
EDIT: Tried following way too, but to no avail.
$fp = fsockopen("tcp://xx.xx.xx.xx", 25003, $errno, $errstr);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
while (!feof($fp)) {
$weight = trim(fgets($fp, 64)," ");
}
}
echo $weight;
fclose($fp);
Where I could be going wrong ? Am I totally on the wrong track ?
Pulling my hair searching from last 4 hours this simple code for socket connection and getting error. I have changed port as well but nothing works.
//create a new WebSocket object.
var wsUri = "ws://localhost:9000/demo/server.php";
websocket = new WebSocket(wsUri);
websocket.onopen = function(ev) { // connection is open
$('#message_box').append("<div class=\"system_msg\">Connected!</div>"); //notify user
}
$('#send-btn').click(function(){ //use clicks message send button
var mymessage = $('#message').val(); //get message text
var myname = $('#name').val(); //get user name
if(myname == ""){ //empty name?
alert("Enter your Name please!");
return;
}
if(mymessage == ""){ //emtpy message?
alert("Enter Some message Please!");
return;
}
//prepare json data
var msg = {
message: mymessage,
name: myname,
color : '<?php echo $colours[$user_colour]; ?>'
};
//convert and send data to server
websocket.send(JSON.stringify(msg));
});
Error :
WebSocket connection to 'ws://localhost:9000/demo/server.php' failed:
Error in connection establishment: net::ERR_CONNECTION_REFUSED
while the PHP is
$host = 'localhost'; //host
$port = '9000'; //port
$null = NULL; //null var
//Create TCP/IP sream socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
//reuseable port
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
//bind socket to specified host
socket_bind($socket, 0, $port);
//listen to port
socket_listen($socket);
//create & add listning socket to the list
$clients = array($socket);
You're not creating a websocket server.
This is what you need: http://socketo.me/
Getting websockets to work properly in PHP is annoying and a mess (especially, if you're a beginner).
You might be over your head.
Your PHP uses a regular (raw) tcp/ip socket connection. Websockets is a protocol with a specific handshake and packet framing... if the server doesn't speak "Websockets", the client will raise an error.
P.S.
PHP was originally designed to act as a web app scripting language for HTTP connections, usually using CGI to quickly return a String that acts as the file/html to be sent.
By nature, PHP processes are intended to have shorter life-spans.
I would not recommend using PHP to write a websocket server, although you could look into Ratchet which is a PHP websocket library that could help you to build a websocket app using PHP.
I recommend you consider Ruby, node.js or Python for your Websocket project - it will save you a lot of headaches as you dig deeper into your project and you are likely to have better community support for any challenges you face along the way.
Try to switch off all antivirus the maybe blocking sockets port for protection.
I have this code:
$requestCount = 0;
$maxRequestCount = 10;
$ip = "192.168.0.100";
$port = 10000;
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$connect = socket_connect($socket, $ip, $port);
while(true){
if($requestCount == $maxRequestCount){break;}
$write = socket_write($socket, $getHTTP, strlen($getHTTP));
echo "Sending TCP message... OK (lenght = $write).<br>";
$out = '';
while($out = socket_read($socket, 65536)){echo "Reading response... OK (lenght = ". strlen($out).")<br>";}
echo "<br>";
usleep(100);
$requestCount++;
}
socket_close($socket);
When the first request is made the connection is already closed (FYN, ACK).
How do i send 10 packets and then the connection is closed?
You can't. Just like a real-world conversation, there is no way to force somebody who isn't interested to keep listening. In the same way, you can't stop the computer on the other end of your socket from closing it.
Judging from variable names in your code, it looks like you're sending HTTP requests (just on a different port). HTTP servers have the option of closing the connection after they respond to the first request they get in that connection. That's what appears to be happening here. You will have to create a new socket and reconnect to send each request.
Another note: TCP doesn't have "packets". It is a stream oriented connection. I know that sounds like a pedantic difference, but it doesn't make sense to ask how you would "send multiple packets without closing the connection", because you don't get to control how TCP sends your messages.
From the packet capture it can be seen that you send 342 bytes to the peer (line 4) and then the peer responds with 1446 bytes (line 6) and after that closes the connection (FIN in line 7). From then on the server will not accept more data from the client and thus any attempts to send more data will be rejected with RST.
I don't know what you are trying to achieve, but since the server closes the connection before the client is done sending the data there is probably some error. You might get more details from the servers response or it might simply be a protocol validation, i.e. the client does not speak the same protocol as the server or not in a proper way. For instance if you would try to use your code to speak with an HTTP server it would be simply wrong because you don't care about keep-alive, body length etc.
Probably the remote end closed the connection.
Probably it's because you have to control what socket_write returns. You have no warranty that socket_write will write your whole buffer at once. If socket_write return 8142 (for example), you have to cut your buffer $getHTTP = substr($getHTTP, 8142); and try a socket_write again. If socket_write(...) === false there is an error and the connection is closed, you have to test it too.
What is the correct way to use socket_select within PHP to send and receive data?
I have a connection to the server that allows for both TCP & UDP packet connections, I am utilizing both. Within these connections I'm both sending and receiving packets on the same port, but the TCP packet will be sent on one port (29999) and UDP will be sent on another port (30000). The transmission type will be that of AF_INET. The IP address will be loopback 127.0.0.1.
I have many questions on how to create a socket connection within this scenario. For example, is it better to use socket_create_pair to make the connection, or use just socket_create followed by socket_connect, and then implement socket_select?
There is a chance that no data will be sent from the server to the client, and it is up to the client to maintain the connection. This will be done by utilizing the time out function within the socket_select call. Should no data be sent within the time limit, the socket_select function will break and a keep alive packet can then be sent. The following script is of the client.
// Create
$TCP = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$UDP = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
// Misc
$isAlive = TRUE;
$UDPPort = 30000;
define('ISP_ISI', 1);
// Connect
socket_connect($TCP, '127.0.0.1', 29999);
socket_connect($UDP, '127.0.0.1', $UDPPort);
// Construct Parameters
$recv = array($TCP, $UDP);
$null = NULL;
// Make The Packet to Send.
$packet = pack('CCCxSSxCSa16a16', 44, ISP_ISI, 1, $UDPPort, 0, '!', 0, 'AdminPass', 'SocketSelect');
// Send ISI (InSim Init) Packet
socket_write($TCP, $packet);
/* Main Program Loop */
while ($isAlive == TRUE)
{
// Socket Select
$sock = socket_select($recv, $null, $null, 5);
// Check Status
if ($sock === FALSE)
$isAlive = FALSE; # Error
else if ($sock > 0)
# How does one check to find what socket changed?
else
# Something else happed, don't know what as it's not in the documentation, Could this be our timeout getting tripped?
}
I'm a bit confused - you seem to be trying to deal with asynchronous requests coming in via 2 sockets but both are acting as clients? This is a very unusual scenario. To be trying to implement them using different protocols (tcp and udp) is even odder (H323 VOIP is the only applciation I know of which does this). A quick google suggests you are trying to write a client for LFS - but why do you need a TCP and UDP client running at the same time? (BTW they publish suitable PHP client code on their Wiki at http://en.lfsmanual.net )
The socket which has data waiting to be read will be in the $recv array after the call to socket_select() (i.e. the array is trimmed down and needs to be repopulated before the next iteration of socket_select()).
If socket_select returns 0 it just means that the sockets are non-blocking and none of them have any data available.
HTH
C.
Here is my code:
<?php
$host = "127.0.0.1";
$portListen = 1234;
$portSend = 1240;
// create socket
$sSender = socket_create(AF_INET, SOCK_STREAM, 0);
socket_connect($sSender, $host, $portListen);
socket_write($sSender, "test", strlen ("test"));
$sListen = socket_create(AF_INET, SOCK_STREAM, 0);
socket_set_option($sListen, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($sListen, $host, $portSend);
socket_listen($sListen,1);
$dataSock = socket_accept($sListen);
echo socket_read($dataSock, 3, PHP_NORMAL_READ);
// close sockets
socket_close($sSender);
socket_close($sListen);
?>
I send "test" to another application, it receives, and send back "ack". Problem is, I can only do it once. If I refresh, I get the address is already used error. I tried the solutions suggested on php.net but to no avail. Trying to socket_shutdown() before socket_close() only give me not connected warning, and upon refreshing will give me a never ending loading.
From what I understand the reason socket is not immediately closed is because there is still data in the buffer. But as you can see I explicitly state to listen to only 1 connection. Plus I am only sending 3 characters from my application and reading 3 in this script.
What am I doing wrong?
edit: The reason I'm using 2 sockets is because I cannot listen() after write() which give me socket is already connected error. Skipping listen() and going straight for read() after write() give me invalid argument error.
I see, after having a few hours sleep and re-analyzing my code and the documentations, I managed to fix everything. You guys are right, 1 socket is indeed enough and the correct way:
<?php
$host = "127.0.0.1";
$portListen = 1234;
$sSender = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n");
socket_connect($sSender, $host, $portListen) or die("Could not connect\n");
socket_write($sSender, "test", strlen ("test")) or die("Could not write output\n");
echo socket_read($sSender, 3, PHP_NORMAL_READ);
socket_close($sSender);
?>
So simple!
After a connection is closed, the socket enters a linger state so that if (during the close) packets were lost and retransmitted, the response would be a clean acknowledgement instead of RST (reset) indicating no such socket was open. It's part of the TCP specification, you can't make it stop happening.
Listen(1) doesn't mean accept only one connection, it means maintain a queue of up 1 connections waiting for an application to accept() them. So as soon as you accept the first, the socket is ready to listen for more.
Like everybody else, I'm wondering why the odd design, but I assume it's a boiled-down example that presents your problem and doesn't necessarily present your real plan.
Why do you need to create 2 sockets for read and write? It looks like an odd design. Client apps usually open a socket connection to the server, then send a request and read the server's response on the same socket.
Also, creating a listening socket (iow a server) won't scale past any firewall or NAT gateway.
Answer to yor comment: No need to listen. just read (possibly blocking operation if your server hasn't replied yet).