Link to home
Start Free TrialLog in
Avatar of deleyd
deleydFlag for United States of America

asked on

PHP emulate Hyperterminal?

Is it possible to write some PHP code that can do what Hyperterminal can do?

In Hyperterminal, I set host address to 10.1.1.116 and port to 10003. Then I do CALL > WAIT FOR A CALL

and I see the Connection request from the remote device:

"CONNECT 1 F0:00:00:00:00:00:00:00"

which gets sent every couple of seconds. (F0:00:00:00:00:00:00:00 is the MAC address we assigned the device.)

Now I would like to do the same thing in PHP using socket programming. I found this page on the topic:

http://christophh.net/2012/07/24/php-socket-programming/

which is close but doesn't quite work.
Avatar of gr8gonzo
gr8gonzo
Flag of United States of America image

Yes, you can sort of do this by creating a socket server, but you'd have to give details on what part of the suggestions on that page did not work.

Not sure what you need the MAC address for in this scenario... usually that stuff is on a different layer of the network communication, so PHP doesn't really deal with it (unless you want to build your own custom extension, which isn't recommended).
Avatar of deleyd

ASKER

Well it works in Hyperterminal, which just shows that the connection is there and we're receiving the data.

I'd like to make this work in PHP; that is, get the same result.

I tried this:
<?php

$addr = gethostbyname("10.1.1.116");

$client = stream_socket_client("tcp://$addr:10003", $errno, $errorMessage);

if ($client === false) {
    throw new UnexpectedValueException("Failed to connect: $errorMessage");
}

echo stream_get_contents($client);
fclose($client);

?>

Open in new window

But that didn't work. Got nothing.
Avatar of deleyd

ASKER

Actually I get:

"Warning: stream_socket_client(): unable to connect to tcp://10.1.1.116:10003 (No connection could be made because the target machine actively refused it."
That code is building a client, not a server. Try the code for creating stream_socket_server.
Avatar of deleyd

ASKER

I get the warning:

"Warning: stream_socket_server(): unable to connect to tcp://10.1.1.116:10003 (The requested address is not valid in its context. )"

for the PHP line:
$server = stream_socket_server("tcp://10.1.1.116:10003", $errno, $errorMessage);

Open in new window

Hmmm, what is 10.1.1.116? Is that the IP for the server or for the remote client?

Whenever you see the message "The requested address is not valid in its context." in ANY programming language, it means that the IP you're trying to use is not bound to any of the network adapters in Windows. It's the same message in .NET, Java, Python, etc, because it's coming from Windows, not from PHP. They all have to go through Windows to allocate that address, and Windows is complaining that it's not a valid address for the computer you're calling it on.
Avatar of deleyd

ASKER

10.1.1.116 is the IP address of the remote device I'm trying to contact.

But it works with Hyperterminal... Though I do have to connect using CALL -> WAIT FOR A CALL. If I just try the usual CALL it says "Unable to connect..."
If you do "WAIT FOR A CALL", you're telling Hyperterminal to act as a server, not a client. Once it's waiting, the remote device is then establishing a connection to Hyperterminal.
That said, I'm not sure what you're trying to accomplish. It sounds like you're not certain about the direction that you want data to flow, or are not understanding what Hyperterminal is doing.
Avatar of deleyd

ASKER

Possibly what I'm trying to do would be done better another way.

I have a web server which someone else wrote which communicates with this device. However, it doesn't handle PHP files, and I was having difficuly figuring out how to process a PHP file within the webserver code.

So thought maybe I could do it the other way around, and bypass the webserver and just have the PHP code talk directly to the device.

However, I have since seen comments saying in general this isn't a very good idea (I don't know if that's true or not.)

I did just an hour ago find an example of another simple web server which does handle PHP files, so perhaps I can use that as a working sample and add PHP support to our existing webserver.

I would also need to add support for *.cgi files. I assume it's done in a similar way and I could figure out how to do it. (That'll have to wait for tomorrow.)
Avatar of deleyd

ASKER

Oh, I should add, since I didn't think to mention it--the idea is users can connect to our website, and there get connected to the remote devices, and our web server running the website will shuffle the data  back and forth, and format it.
CGI files are typically Perl, so that's a different folder, but I would agree with those comments that this is probably the wrong way to go about it.

#1. Web servers are designed specifically FOR this kind of of purpose - serving PHP and CGI and other kinds of files. If they don't already have that functionality, in MOST cases you can add the support for it.

#2. The PHP code has to be called somehow. If it's not called from the web server, then you'd need to call the engine directly. That's fine while you're developing, but you'll have to think about how you want this to be executed / restarted/ maintained without your help.

#3. Executing the PHP code outside the context of the web server also changes various bits of valuable information that is accessible to PHP, like the remote IP.

You mentioned that someone else "wrote" the web server. I hope that someone didn't just write a web server from scratch. There are plenty of existing, solid web servers out there. This is one area where 99 times out of 100, you do not need to re-invent the wheel.

Apache is one of the most common, free web servers that is extremely solid with a ton of community (and commercial, if you want) support, and is easily installed, maintained, and works great with both PHP and CGI (Perl) files. There are various ways to get support added to Apache, but most people use plugins called mod_php and mod_perl.

If the server is running Windows, sometimes people use the IIS web server instead, but this isn't as common outside corporate environments.

It would be a very wise investment of time to learn more about the existing web server. In most cases, your best and fastest solution is to add PHP support to the existing web server and just let it do it's job.

Trying to write a socket server from scratch can be a very large and VERY time-consuming undertaking (it may not seem like it at first, but it's one of those I-didn't-think-about-that programming games) unless you've done it several times before.
One last note - I'm still not sure how the communication happens with the remote devices. Network communication typically happens by this process:

1. Device A (the host) begins to listen for a request on port X. This is like someone standing right behind the front door of a house and waiting for a visitor to come up.

2. Device B (the guest) attempts to open a socket connection to Device A's IP address on port X. This is like the visitor ringing the doorbell.

3. Since Device A is right there and listening for the doorbell, it opens the front door and accepts the request to establish the socket. Now data can flow between the host and the guest.

4. Each device can push and pull data. So when the front door first opens, it might be the host's responsibility to push data to the guest, saying "Hello and welcome!" Since it's typical greeting protocol between humans for this to happen, the guest waits patiently for the host to say this, and then pulls the data (this means the guest hears the "Hello and welcome!"). Once the guest hears that, the guest responds in kind and makes a request, "Hi! Can I use your bathroom?" The host keeps pulling the data until the guest finishes talking, and then says, "Sure!" and so on.

5. Once the conversation is over (when the guest leaves or when the host just forces him out by closing the front door because, hey, that's his house), the front door is closed and the host continues to wait behind the front door for the next visitor.

This is a very general look at network communication. You said that the website facilitates communication between the user and the remote devices, so that would imply that the remote devices are hosts and the web site (web server running PHP, actually) is the guest. I would also assume that given the port number in your question, that this is the port that the remote devices are listening on.

If that's all correct, then you would indeed want to create a socket client in PHP (assuming PHP is running from the web server) that connects to the socket servers already running on the remote devices. If you have a telnet client (Hyperterminal can work), you can always test this by telnetting to one of the remote devices' IP addresses using that port instead of the typical telnet port (23). If the remote device is indeed listening, then you should be able to make the connection and start sending/receiving data between telnet and the remote device. Just make sure that you're running telnet from a different device than the one you're connecting to!
Avatar of deleyd

ASKER

There is indeed concern that this web server one of our remote employees has written might not scale well. It works fine when we test it, with only a few people connecting, but not sure how it will fare in the field as many people start connecting to it. It might be overwhelmed.

Our remote devices are currently designed to not accept any incoming connection requests. Instead they make an outgoing connection request to our web site. The idea was that would be more secure, so not just anyone can connect to these devices and mess with them.

So we have a web site, and a web server, listening for connection requests from our devices, accepting the connection requests, and then our website has a connection with our devices.

Then our web server matches up devices with users, so users get to communicate with their devices, the ones they are authorized to connect to (according to some database that says which devices a particular user can connect to).


One problem I've wondered about (I didn't design any of this so far, someone else did) is does that mean we'll have hundreds of devices all with active connections to our website, even though most of them no one will be looking at? What problems will that cause having all these connections with nobody actually using them most of the time? Will we have a waste of resources problem?


An interesting 3rd choice you brought up--perhaps I could write some sort of add-on enhancement for the Apache web server so the Apache web server will listen for connection requests from our remote devices, accept the connection request, and then the web server has a connection with our remote devices?
It's a pretty risky setup when you're dealing with homegrown web servers. Apache and IIS have both been the dominating presences in that field and even with HUGE teams of skilled developers, they are constantly fixing security bugs. Unless the remote employee happened to be a flawless god among developers, this probably means that the homegrown web server has several undiscovered security flaws.

Outgoing connections from the remote devices might actually be LESS secure (especially when combined with a homegrown web server). It means that if someone can exploit the web server, they could potentially have unlimited access to all the devices. This would be likely easier than circumventing good security mechanisms on each device (IP restrictions, client certificate authentication, etc...), and it is a model that likely will not scale well. As you correctly stated, the current model means constant, active connections for all the devices, and that results in constant use of network resources that could be allocated for users instead. Each connection also likely utilizes a child process that consumes memory and CPU, too, and is subject to drop any time there are network problems.

As long as the remote devices can support reasonable security measures, there's no reason that they shouldn't be the ones listening for connections rather than maintaining constant connections.
Avatar of deleyd

ASKER

OK I switched the device to accept incoming connection requests.

Actually what we have is a Lantronix "Serial to Ethernet" box. The device sends data out a serial port to the Lantronix, and the Lantronix takes care of handling the internet.

So I switched the Lantronix on our test device to accept incoming connection requests, and I am able to connect to it with Hyperterminal (no longer need to use "Call -> Wait For A Call", now just connect). I see the data from the device, and I can send the device commands and it responds.

And I'm back to where I was at the beginning, wondering if I can communicate with this device using PHP code the way Hyperterminal is communicating to it now. So far no luck.

The Hyperterminal settings are:
Host address: 10.1.1.116
Port number: 10001

PHP Tried:
$client = stream_socket_client("tcp://10.1.1.116:10001", $errno, $errorMessage);
fwrite($client, "GET / HTTP/1.0\r\nHost: 10.1.1.116\r\nAccept: */*\r\n\r\n");
echo stream_get_contents($client);
fclose($client);

Open in new window

gives me: "Warning: stream_socket_client(): unable to connect to tcp://10.1.1.116:10001 (No connection could be made because the target machine actively refused it. )"

Or I get no response at all and the web page never loads, the browser just sits there spinning it's wheel that means the page is loading. (Perhaps line 2 isn't correct?)

Also tried:
$server = stream_socket_server("tcp://10.1.1.116:10001", $errno, $errorMessage);

Open in new window

gives m: "Warning: stream_socket_server(): unable to connect to tcp://10.1.1.116:10001 (The requested address is not valid in its context.)"

I think I'm a client now that I set the Lantronix to accept incoming requests, so I'm not sure I think stream_socket_server isn't correct anymore.
Avatar of deleyd

ASKER

SOME SUCCESS.

<?php

$sock = stream_socket_client('tcp://10.1.1.116:10001', $errno, $errstr);

if ($sock === false) {
    throw new UnexpectedValueException("Failed to connect: $errorMessage");
}

echo fread($sock, 4096)."\n";
fclose($sock);

?>

Open in new window

The above code connects and retrieves one packet of data from the remote device. It blocks until some data comes in.

I can also send a command and read the first packet of response data:
<?php

$sock = stream_socket_client('tcp://10.1.1.116:10001', $errno, $errstr);

fwrite($sock, '001Kö '."\r\n");  //send a command

if ($sock === false) {
    throw new UnexpectedValueException("Failed to connect: $errorMessage");
}

echo fread($sock, 4096)."\n";
fclose($sock);

?>

Open in new window

Now I just need to expand this to something more general, such as read all the packets of data that come in, and send out certain commands.
Avatar of deleyd

ASKER

OK here's a question. I have a website page (HTML, but may have been created using PHP), and I want the page to receive data from the remote device and update the screen real time as the new data comes in.

Can this be done in PHP using sockets, or does it have to be done in JavaScript using AJax requests? (in which case do I have the problem of Ajax not allowing cross domain calls?)
The updates on the screen happen between the browser and the web server, and the browser will not retain a connection to the web server, because HTTP is stateless - the browser downloads the page and closes the connection.

So if you want to update the screen after the initial page has loaded, then you would need to use Ajax to have the browser issue a new request to the web server for an update. The web server (via PHP) would receive the request, create a new connection to the device, communicate the request to the device, get the response data, and push that data back to the browser. You shouldn't have a problem with cross-domain calls because the browser isn't sending its update requests to a different domain - it would just hit another script on the same server, I would assume.
Avatar of deleyd

ASKER

Will I need to write an Apache module?

And how about HTML5 websockets?
ASKER CERTIFIED SOLUTION
Avatar of gr8gonzo
gr8gonzo
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of deleyd

ASKER

Thank you for the very helpful responses. I'm submitting a continuation question so you can get more points. The continuation question is at:

https://www.experts-exchange.com/questions/28247367/PHP-stream-socket-client-works-sometimes-TCP-IP-frames-explanation-needed.html