I have a GPS unit that can send data over a TCP connection, but I don't have the ability to modify the message that it sends so it would come to my server in the form of an HTTP request - it can only send a message in a predefined format.
So, I have the following questions:
1) Is it possible to have Apache handle a TCP connection that doesn't come in the form of an HTTP request, and have the message that is sent be processed by a PHP script?
2) If #1 isn't possible, how would you recommend I handle the data being sent to my server?
I will potentially have hundreds, if not thousands, of these GPS units sending data to my server so I need an efficient way to handle all of the connections coming in (which is why I wanted Apache or some other production worthy server to handle the TCP connections). I would like to be able to deal with the message sent over the connection with PHP since that is what the rest of my application runs on, and I will need to insert the data sent into a database (and PHP is really good at doing that kind of thing).
In case it matters, the GPS unit can send data over a UDP connection, but from what I have read Apache doesn't work with UDP connections.
Any suggestions would be welcome.
To answer your questions:
1) Not without major modification
2) Build your own server. This is easily done with several platforms and in several languages. I personally like to use the Twisted Framework because Python is relatively simple to use and the framework is very flexible.
Using Apache wouldn't be practical as it's using a nuclear bomb when a firecracker will suffice. Creating a PHP server is quite simple on Linux with the help of xinetd.
Modify /etc/services. Say you want your service to run on port 56789. In /etc/services, add the line:
gpsservice 56789/tcp
In /etc/xinet.d/, create a file named gpsservice:
service gpsservice
{
socket_type = stream
protocol = tcp
wait = no
user = yourusername
server = /path/to/your/script
log_on_success = HOST PID
disable = no
}
Create your PHP script (chmod it to be executable):
#!/usr/bin/php
<?php
// do stuff
?>
Restart xinetd service xinetd restart
You now have a quick TCP server written in PHP.
Related
For a new project I need to implement remote desktop protocols. The addresses of the remote need to be secured and may never get sent to the client. After a lot of research and some tests I found Guacamole, which also has a Java client. The project is designed as an API though, so I started porting some bits of the Java client example to PHP.
The use case will be the following:
User logs into my service (Laravel application)
WebSocket connection establishes to a constantly running PHP script (using HOA\WebSocket)
Upon authorization a TCP socket needs to be established to the Guacamole Daemon
Commands coming via WebSocket need to be directed to the Guacamole Daemon and vice versa
What makes this complicated is the fact that the application needs to be able to serve multiple clients simultaneously. Multiple TCP sockets need to be established and multiple WebSocket connections need to be managed all at once.
For my simple test I opened the socket via fsockopen and then looped to wait for data. With this I obviously can't listen to multiple sockets at once (at least realistically), but I stumbled upon the React Socket Client library:
Think of this library as an async version of fsockopen() or stream_socket_client().
This sounds like it is what I need, but then again, I'm using HOA and its WeSocket server, which apparently also runs in a loop (when invoking WebsocketConnectionHandler->run()).
Should I even be using React's Socket Client or should I try to use HOA's Socket library instead (seeing as I'm already using WebSocket from that)? Are React and HOA even compatible in their event loop, so could I listen to WebSocket clients and a TCP connection at the same time?
If so, could anyone give me some hints or examples on how to get started with coupling these two? Thanks!
The target is simple: clients post http requests to query data and update record by some keys。 Highest request: 500/sec (the higher the better, but the best is to fulfil this requirement while making the system easy to achieve and using less mashines)
what I've done: nginx + php-cgi(using php) to serve http request, the php use thrift RPC to retrieve data from a DB proxy which is only used to query and update DB(mysql). The DB proxy uses mysql connection pool and thrift's TNonblockingServer. (In my country, there are 2 ISP, DB Proxy will be deployed in multi-isp machine and so is the db, web servers can be deployed on single-isp mashine according to the experience)
what trouble me: when I do stress test(when >500/sec), I found " TSocket: Could not connect to 172.19.122.32:9090 (Connection refused [111]" from php log. I think it may be caused by the port's running out(may be incorrect conclusion). So I design to use thrift connection bool to reduce thrift connection. But there is no connection pool in php (there seem to be some DB connection pool tech) and php does not support the feature.
So I think maybe the project is designed in the wrong way from the beginning(like use php ,thrift). Is there a good way to solve this based on what i've done? And I think most people will doubt my awkward scheme. Well, your new scheme will help a lot
thanks.
"TSocket: Could not connect to 172.19.122.32:9090 (Connection refused [111])" from php log shows the ports running out because of too many short connections in a short time. So I config the tcp TIME_WAIT status to recycle port in time using:
sysctl -w net.ipv4.tcp_timestamps=1
sysctl -w net.ipv4.tcp_tw_recycle=1
it works!
what droubles me is sloved, but to change the kernal parameter will affect the NAT. It's not a perfect solution. I think a new good design of this system can be continue to discuss.
I used to have a small chat app(which was almost working), that uses PHP, jQuery and MySQL. The volume of users is very small (only my friends uses it). I used long polling method for this.
And now, I am thinking about using HTML5 Websockets for this, because it is a lot more efficient. And also most of my friends are using Google Chrome(which already supports HTML5). I have gone through some tutorials that talks about HTML5 websockets. And I have downloaded the phpWebSocket from github. I have gone through the code. But the readme file says that the PHP page that listens to incoming connections should be run using "PHP -q" from commandline. So, I have searched what this "q" flag would do. And I found that it runs the page in quiet mode. So, when I run this in quiet mode what is happened ? It would run endlessly ? Will this running process affect the system resources ?
This PHP page should run the entire time. Then only the connections could be accepted. Isn't it ?
I am having a shared hosting package with HostGator. And they allow cron jobs too. And my present chat app(that uses long polling method) inserts all the messages to database. When the user polls, it would search for any new messages from the database and then output them (if any).
So, I am bit stuck here. :(
It should be run from the command line because as you suspected, it is intended to run endlessly. It binds to a socket on the server and listens for incoming connections. It can't be reliably run from the browser.
The "-q" option tells it not to output any browser headers such as X-Powered-By: PHP or Content-Type: text/html
It will consume as much memory as PHP requires as long as its running. Your memory footprint on startup with no clients will vary between configurations. The more connected clients, the more cpu, memory and socket descriptors you will use. It uses select so it is efficient socket handling.
Also, since you're on shared hosting, you probably won't be able to use it because your user will most likely not have the ability to bind to a port and listen for connections.
As you can see in the demo, the URL to connect the WebSocket to is ws://localhost:12345/websocket/server.php. Unless you have a webserver capable of using WebSockets, you will have to run something like phpWebSocket that acts as a server and listens on a port other than 80.
Hope that helps.
The shared hosting package for HostGator does not allow clients to bind to local ports for incoming. This might be part of the problem.
http://support.hostgator.com/articles/pre-sales-policies/socket-connections
1- Let's say my computer ip address is 111.11.111.11, and the server that my php script is on is 222.22.222.22, so if i access and run the php script that is on the server and start a socket server, which ip do my clients need to connect to?
2- Is it possible to have a socket running on php which keeps reading, and responding to the clients until I close the browser, So basically what i'm trying to do is to start a socket which keeps reading, and accepting clients, and keeps communicating with them multiple times with each.
thanks for the answer, but i think i didn't explain well enough on my question 2, so let me make it easier:
Is it possible to create a chat server using php? because the point i was getting into was if it's possible to accept multiple clients and keep them alove.
222.22.222.22. But it sounds like you are starting up a socket server in response to a HTTP request. Probably, that won't work as intended, since the PHP interpreter terminates after the response is sent. If you had permissions, you could fork a separate socket server process, but I don't know what that would accomplish.
No. Even if you kept the interpreter running, there is no way to tell when the browser closes. The closest you can get is determining the browser (as determined by cookies or IP) stops communicating with you.
1- 222.22.222.22, your server's IP.
2- When a visitor arrives you can spawn a 'socket process' and implement a client side 'heartbeat' application using JavaScript/AJAX, but that implies you running the socket backend script (possibly) for a long time, which may cause problems (Like having a lot of PHP processes open, depending on the way your web server is set up this may cause problems)
I am working on an iPhone game which is depended on a LAMP server. I want to create a "event" based system where the apache server sends an event to the iphone.
For this, I am thinking of using "CFStreamCreatePairWithSocketToHost" to connect to port 80 of the apache server.
I am able to successfully connect to the server and open a read and write stream via the iPhone, but I am not sure how to send data to the iphone using PHP running from the LAMP server to the iPhone.
I think I can use fsockopen in php to open a socket connection and write data to that socket. I tired running this code
$fp = fsockopen("tcp://localhost", 80, $errno, $errstr);
if (!$fp) {
echo "ERROR: $errno - $errstr<br />\n";
} else {
echo"writing to socket ";
fwrite($fp, "wwqeqweqw eqwe qwe \n");
//echo fread($fp, 26);
fclose($fp);
echo "done";
}
But, I dont see anything being read on the iphone.. Any idea what's going on, or how to accomplish this?
Thanks!
Mmm, using PHP to listen for incoming connections is sub-optimal, it's not really what it was built for. Is there no way of using the "normal" HTTP based communication channels, making a plain request to a URL and parsing the returned data in whatever format you prefer?
Anyway, check out
Run PHP script as daemon process
Is it wise to use PHP for a daemon?
and more: Search
HTTP isn't really a streaming protocol, you send requests and get responses from it. You may want to look at something other than apache/php to fulfill this requirement
... or heed Pekka's advise and break your requirements down to simple request responses. i.e. poll your server at regular intervals to see if there is any data waiting for the iphone to process... note I'm not advocating this as its not very pleasant on the network or the programmer, but its a possability.
Another way is to build your own service (do not use apache) that will accept connections on a particular port which your iphone can connect to, and communicate that way - you can even run a PHP script this way if you so desire (however read the links that Pekka provided).
Yet another way is to build the server into your iphone application which your webserver can connect to - however this is a bit silly as your server is probably online more than your iphone is (as the iPhone's apps do not run in the background if it is unjailbroken, and iphone 4.0 is not released to the general public yet).
Options none-the-less :)
Matt
Use a 'pull' instead of 'push' model...
Browsers are generally designed to be stateless. There are ways around that limitation but not to do what you're describing.
Because, servers are never expected to 'push' data to a client. That would mean that the server would have to be conscious of the presence, location, and medium to transfer data to a client, which they generally aren't.
Instead of trying to get the server to push the event to the client on the iPhone. Have the server store the state and have the iPhone frequently poll for the application state using AJAX.
If you want an app with a direct 1-1 connection between server and client LAMP/PHP is the wrong way to go because you'd need LAMP to be running on both the server and the iPhone to accomplish what you're describing. IE, you can't 'push' data from a HTTP server to a HTTP client you can only return data that's requested from the server to the client.