On a page load, I'm consistently requesting data from the same API. Is there any way to keep a cURL connection alive across multiple page loads to reduce handshake time? I know you can make multiple cURL requests with keep-alive headers on the same PHP process easily, but I want a connection to stay alive for say a set amount of time rather than when the process is finished.
It seems like I'd need some sort of Daemon plugin to do this. I'm very open to alternatives solutions. It doesn't have to be cURL. I've been searching and have had no luck whatsoever.
Thanks!
I would say using pfsockopen() to create a persistent connection would make the trick. You can open the socket to the HTTP API server and then make multiple petitions, and close the socket when the page load ends.
<?php
$host = "protocol://your-api-hostname.com/";
$uri = "/your/api/location";
$port = 80;
// For an HTTP API, for example:
$socket = pfsockopen ($host, $port, $errno, $errstr, 0);
if (!$socket) {
echo $errno. " - " . $errstr;
} else {
// You can do here as many requests as you want.
fputs ($socket, $request1);
fputs ($socket, $request2);
// And then keep on reading until the end of the responses
$i = 0;
$a = array();
while (!feof($socket)) {
$a[$i] = fgets($socket);
$i++;
}
fclose($socket);
I don't know if that is exactly what you need but it offers you more options than cURL.
Related
I'm in the process of creating my own service status script as both a chance to become more familiar with the PHP language and to design it from the ground up as being as efficient as possible for my needs.
A section of my code used in both my cron job and testing a connection parts queries the IP/Port of a service to make sure it is online. My issue is that the script simply queries whether the port is "Unblocked" on that IP so if for instance I was querying port 21 with an FTP server and that FTP server crashed my script would not detect any changes meaning its not doing what I want it to do. Instead I would be wanting the IP and port to be queried and for my script to see if there is actually something running on that port, if there is show online if not error out. I've had a look on google and it seems like I would have to send a packet/receive a response so PHP can tell there's something active? I'm not sure.
This is my current code below:
<?php
$host = $_POST['servip'];
$port = $_POST['servport'];
if (!$socket = #fsockopen($host, $port, $errno, $errstr, 3)) {
echo "Offline!";
} else {
echo "Online!";
fclose($socket);
}
?>
http://php.net/manual/en/function.fsockopen.php
fsockopen — Open Internet or Unix domain socket connection The socket
will by default be opened in blocking mode. You can switch it to
non-blocking mode by using stream_set_blocking(). The function
stream_socket_client() is similar but provides a richer set of
options, including non-blocking connection and the ability to provide
a stream context.
Since fsockopen will either connect or not connect (timeout) then that tells you whether or not a connection is available ("open") or being blocked (firewall, etc).
// Ping by website domain name, IP address or Hostname
function example_pingDomain($domain){
$starttime = microtime(true);
$file = #fsockopen($domain, 80, $errno, $errstr, 10);
$stoptime = microtime(true);
$status = 0;
if (!$file) {
$status = -1; // Site is down
} else {
fclose($file);
$status = ($stoptime - $starttime) * 1000;
$status = floor($status);
}
return $status;
}
If you really want to know if the FTP server is working or not, your best option is to actually send FTP commands through to it.
An FTP server, upon connect, should typically reply with the first three bytes "220" or "120". 220 is a "greeting". You can read more in RFC 959.
To be completely sure, you might be better off using ftp:// handling in PHP, e.g. actually authenticating a user (maybe user authentication is broken, but it's still able to send a greeting - does that count is "down"?)
Anyway, if you want better than "was I able to connect on that port?" or "did the connect succeed in a timely fashion?", you have to delve into actual communication over the socket. Ultimately, this means you have to do something special for each type of service (for some, read bytes, for others write bytes, etc.)
I have a client-server application, in which the server may require to send information back to clients.
As the client-server pattern does not allow the server to "request" the client, there are 2 solutions:
The client pull the server every few time (which is a bad solution)
The client maintain an open socket with the server, that allow the server to send new information back when required.
Currently, the client (Web app with JavaScript and Html/Css) open a streaming connection to the server (A C++ server) which may send information back to the client.
I would like to implement a PHP version of this feature to allow low-cost hosting to work with my program (low-cost hosting usually does not provide access to install/run binaries).
The idea is that the client make a request that establish the streaming socket, it save the socket and then, an other request may retrieve this socket and send new information through it.
So, my question is:
How to save an http socket in PHP, so a further request may retrieve it?
How to finish the PHP script without closing the socket?
How to save socket information?
How to retrieve the socket from a new thread/request?
I do not know even if that is possible, I read about pfsockopen, but it seem a bit different to what I need ( I may be wrong ).
So, you need two connections for each client, one persist for get data from server, and other to send data to.
Something like:
in persist.php:
$socket = stream_socket_server('unix:///tmp/unique.sock', $errno, $errstr);
if (!$socket) {
echo "$errstr ($errno)<br />\n";
} else {
while ($conn = stream_socket_accept($socket)) {
$buffer = "";
// Read until double CRLF
while( !preg_match('/\r?\n\r?\n/', $buffer) )
$buffer .= fread($client, 2046);
//Operate with our listener
echo $buffer;
flush();
// Respond to socket client
fwrite($conn, "200 OK HTTP/1.1\r\n\r\n");
fclose($conn);
}
fclose($socket);
}
in senddata.php:
$sock = stream_socket_client('unix:///tmp/unique.sock', $errno, $errstr);
fwrite($sock, $data);
fflush($sock);
fclose($sock);
One way to solve it - forget about sockets.
Pseudocode:
// receive request, set some session_id if not exists
// request contains last_timestamp, so we know which data client already have
// check have we any dataset for this session_id after last_timestamp
// return this dataset, or no_new_data signature
Data can be stored in database, for example.
I know that PHP does allow you to create a server but what about client? I would need a script that connects to my TCP/IP server on given port and send some data. Is that possible in PHP and if so, could you help me please? I did not find anything useful.
I have my TCP/IP server running on port 1301 and I would need users to be able by clicking on web page send one char to the server.
It's similar to how you would create a server. I'd recommend taking a look at the documentation for socket_connect.
Summaries:
socket_create
socket_bind
socket_connect
socket_write
socket_read
socket_close
Workflow:
Create the socket
Optionally bind it
Connect to the server
Read/write data
Close the socket
I've used this piece before. It's fairly simple; it connects to $ip_address on port $port, and sends the $sendData data to the server, and then reads the response and returns the response.
$sendData = chr(6).chr(0).chr(255).chr(255).'info';
function sendAndGetResponse($ip_address, $port, $sendData){
$socketHandler=#fsockopen($ip_address, $port, $errno, $errstr, 1);
if(!$socketHandler)
{
return false; //offline
}
else
{
$response = '';
stream_set_timeout($socketHandler, 2);
fwrite($socketHandler, $sendData);
while (!feof($socketHandler))
{
stream_set_timeout($socketHandler, 2);
$response .= fgets($socketHandler, 1024);
}
fclose($socketHandler);
return $response;
}
}
You can use CURL if it is HTTP server or create a socket connection http://php.net/manual/en/function.socket-connect.php
Yes, php can act as a HTTP-client with CURL, fsockopen and most easiest way to fetch URL - with file_get_contents()
I have a situation where I need to update one browser window based on input from the other. Right now I'm using WebSockets and it's working great.
Now I want to send data to the WebSocket using PHP instead of the browser (so instead of ws://, use PHP code). In other words, I want to simulate the WebSocket.send() call using PHP instead of JavaScript.
I have the following code which doesn't seem to work (the onmessage is not being called):
if (
function_exists('socket_create') AND
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP) AND
$sock_data = socket_connect($sock, "127.0.0.1", 12345)
) {
$msg = "hello world";
$sock_data = socket_set_option($sock, SOL_SOCKET, SO_BROADCAST, 1); //Set
$sock_data = socket_write($sock, $msg, strlen($msg)); //Send data
socket_close($sock); //Close socket
}
Here's how it's done:
http://permalink.gmane.org/gmane.comp.lang.javascript.nodejs/18088
$host = 'localhost'; //where is the websocket server
$port = 9000;
$local = "http://localhost/"; //url where this script run
$data = 'hello world!'; //data to be send
$head = "GET / HTTP/1.1"."\r\n".
"Upgrade: WebSocket"."\r\n".
"Connection: Upgrade"."\r\n".
"Origin: $local"."\r\n".
"Host: $host"."\r\n".
"Content-Length: ".strlen($data)."\r\n"."\r\n";
//WebSocket handshake
$sock = fsockopen($host, $port, $errno, $errstr, 2);
fwrite($sock, $head ) or die('error:'.$errno.':'.$errstr);
$headers = fread($sock, 2000);
fwrite($sock, "\x00$data\xff" ) or die('error:'.$errno.':'.$errstr);
$wsdata = fread($sock, 2000); //receives the data included in the websocket package "\x00DATA\xff"
fclose($sock);
In order to send data to the socket, you need to use fsockopen to open the connection to the socket at specified port. If the connection is successfully, all you need to do is use fwrite
However, you are going to be sending the data to the WebSocket server. The server will treat you as a client, and since you are not providing HTTP headers it expects for successful authentication - your connection will be refused.
Since you didn't say who is supposed to receive the message you are trying to send (all users or a specific user or something entirely different), without knowing what your goal is - it's hard to explain any further what you should do.
There is a lot more to WebSockets than just sending the raw data to a TCP socket.
Ok, to start, you're using a UDP socket, where WebSockets use TCP. WebSockets is an entire protocol for communication, similar to HTTP, so you need to follow that protocol, there is a handshake step that you need to perform first and headers you need to add to all communication. It's not difficult, but I'm not going to go into detail here.
You have two options from here, implement the WebSockets protocol in php, or use a pre-built library like this one: http://code.google.com/p/phpwebsocket/
I'm not being rude, or mean, but in the future, try a quick Google search. That library I linked was found after googling "PHP WebSockets".
The most important part is that the message needs to be sent on the existing socket, meaning you cant call socket_connect, fsockopen, or any other function within PHP that will attempt an unsolicited connection to the client. This isn't a websocket thing - that's a fundamental concept in network programing.
On phpwebsocket it would be somethin like:
$msg = "hello world";
$phpwebsocket->send($user->socket, $msg);
where '$phpwebsocket' is the PHP WebSocket object, $user->socket is a connected user who connected priory using with a javascript WebSocket(), and send() is a method within the WebSocket object that will properly encode the message into a frame (or should as it will soon be required).
However, if for any reason you want to connect to the websocket server using websockets from PHP, you'll want to check out https://github.com/nicokaiser/php-websocket. The server in the link wont be of any importance if your happy with your current solution, but the package also contains a PHP Websocket client class which is what you would need.
Checkout ratchet
You can use something like telnet with popen/proc_open to communicate with the socket server.
I'm playing around with the IMAP protocol in PHP using fsockopen to send and receive commands. My preliminary experiments work but are insanely slow. It takes about 2 minutes for the simple function below to run. I've tried several different IMAP servers and have gotten the same result. Can anyone tell me why this code is so slow?
<?php
function connectToServer($host, $port, $timeout) {
// Connect to the server
$conn = fsockopen($host, $port, $errno, $errstr, $timeout);
// Write IMAP Command
$command = "a001 CAPABILITY\r\n";
// Send Command
fputs($conn, $command, strlen($command));
// Read in responses
while (!feof($conn)) {
$data .= fgets($conn, 1024);
}
// Display Responses
print $data;
// Close connection to server
fclose($conn);
}
connectToServer('mail.me.com', 143, 30);
?>
This is the response I get back:
macinjosh:Desktop Josh$ php test.php
* OK [CAPABILITY mmp0613 IMAP4 IMAP4rev1 ACL QUOTA LITERAL+ NAMESPACE UIDPLUS CHILDREN BINARY UNSELECT SORT LANGUAGE IDLE XSENDER X-NETSCAPE XSERVERINFO X-SUN-SORT X-SUN-IMAP X-ANNOTATEMORE X-UNAUTHENTICATE XUM1 AUTH=PLAIN STARTTLS] Messaging Multiplexor (Sun Java(tm) System Messaging Server 6.3-6.03 (built Jun 5 2008))
* CAPABILITY mmp0613 IMAP4 IMAP4rev1 ACL QUOTA LITERAL+ NAMESPACE UIDPLUS CHILDREN BINARY UNSELECT SORT LANGUAGE IDLE XSENDER X-NETSCAPE XSERVERINFO X-SUN-SORT X-SUN-IMAP X-ANNOTATEMORE X-UNAUTHENTICATE XUM1 AUTH=PLAIN STARTTLS
a001 OK CAPABILITY completed
It seems like feof won't return true until the remote side times out and closes the connection. The $timeout parameter that you are passing only applies to the initial connection attempt.
Try changing your while loop to print the status directly:
while (!feof($conn)) {
print fgets($conn, 1024);
}
Or change your loop exit condition to break after its read the full reply. It would probably have to be smarter about the protocol.
Finally, I have to ask, why aren't you using PHP's built-in IMAP client?