I'm trying to develop a webchat with HTML5 websocket (with hybi-17 protocol) but I've some problems with chars decoding.
This is what I send through the client (user-agent: Firefox 7):
var socket = new MozWebSocket ('ws://localhost/server.php');
socket.onopen = function () {
alert ('Opened!');
}
Then, I send these data:
socket.send ('Hello');
socket.send ('World');
And this is the server-side code:
$bytes = #socket_recv ($socket, $buffer, BUFSIZE, 0);
if (($bytes == 0) || ($bytes == 2)) {
this->disconnect ($socket);
}
else {
echo $buffer;
}
While this is the data recevied echoed:
��6S~g?Y (Hello)
���~����� (World)
As you can see, the socket is opened and data travels from the client to the server.
The server works with PHP5 and uses normal socket functions to build the connection.
How can I decode that unreadable string in a human readable one?
Thanks in advance.
You have made one of the most common errors people make when they first start writing code that uses TCP -- you forgot to implement the protocol!
In your case, you forgot it in the server. The client already has a WebSocket implementation, and you request it by creating a 'MozWebSocket' object. The WebSocket specification says, "Each frame starts with a 0x00 byte, ends with a 0xFF byte, and contains UTF-8 data in between." Where's the code in the server to find the start of a frame and the end of a frame? Where the code to discard the 0xFF byte?
You actually have to implement the protocol. The protocol specification tells you how to decode the received data. (In your case, the data you are seeing as junk is most likely part of the protocol handshake -- the part that looks like ^n:ds[4U in this description of the handkshake phase.)
I'm pretty sure your method of invoking a PHP script to handle the WebSocket call through the web server will not work. That is, unless your web server knows how to do this -- WaterSpout and phpdaemon do.
Using the base server.php and client.html from http://code.google.com/p/phpwebsocket/ along with modification from HTML5 WebSocket with hybi-17 to deal with the single key standard I can successfully send one message to the server before it closes unexpectedly. It's at least a step closer just not sure as of yet why it closes after one successful message.
Related
Hello I'm quite new to using sockets and am not that familiar with them yet, Basically all i am trying to do is pass a string variable to a web address (e.g. www.example.com/index.php?Example=StringExample) and then get a response, so for example it would return "Test Example" if index.php looked like this:
<?php
if($_GET['Example'] == "StringExample")
{
echo "Test Example";
}
?>
Here is what I've tried in c++:
struct sockaddr_in SocketAddress;
hostent* addr = gethostbyname("www.example.com/index.php?Example=StringExample");
int sizeofaddr = sizeof(addr);
SocketAddress.sin_addr.s_addr = inet_addr(addr->h_name);
SocketAddress.sin_port = htons(80);
SocketAddress.sin_family = AF_INET;
SOCKET Connection = socket(AF_INET, SOCK_STREAM, NULL);
if (connect(Connection, (SOCKADDR*)&addr, sizeofaddr) != 0)
{
return 0; //Failed to Connect
}
char buffff[256];
recv(Connection, buffff, sizeof(buffff), NULL);
//"Test Example" now stored in buffff
What am i doing wrong?
Btw in my case i would not like to use any libraries like boost or anything like that. Thanks for the help :)
gethostbyname("www.example.com/index.php?Example=StringExample");
"www.example.com/index.php?Example=StringExample" is not a valid server name. This is an entire URL; a server name would be "www.example.com". gethostbyname() takes the name of a server, and not a URL, and returns its IP address. Additionally, gethostbyname() has been obsoleted. New code should use the getaddrinfo(3) function, instead.
This is obviously an HTTP URL. To download a document via HTTP it is a lot more work than just connecting a socket. Establishing a socket connection is just the first step in the process of downloading a document from an HTTP server. This must be followed by sending a valid HTTP request, and then receiving an HTTP response from the server.
There are many libraries, such as curl, that implement the entire client-side process needed to download an HTTP document, that will handle the socket connection themselves.
But there's nothing wrong with trying to implement this yourself, either. It's a good programming excersize.
So, after resolving www.example.com's IP address, you will need to
1) Connect to the server's port 80, the default HTTP port.
2) Send an HTTP request for "/index.php?Example=StringExample".
3) Parse the HTTP response.
The specification for HTTP requests and responses is defined by RFC 2616, which you can consult for complete documentation of how HTTP requests and responses are structured.
If you want to access a web server with sockets, you have to keep in mind:
You can open a tcp/ip connection to your web server
BUT afterwards you have to do the http protocol by yourself
In case of your example:
hostent* addr = gethostbyname("www.example.com");
//...
const char* request = "GET index.html"
send(Connection, request, strlen(request), NULL)
//fetch index.html with a recv and parse it
To be more precise, if you want to access your server, you have to take a look how GET, PUT, POST, etc. are implemented in the http protocol, send the proper commands to your web server and recv() the replies
I have a device with relays connected to my network. I am able to connect to device via the built in url host to turn on and off the relays. What I would like to do is be able to send commands to the device turning on and off the relays either via php, vb code or make my own ASP url's for each relay that will do that same thing. I am using Visual Studio 2013.
I have the IP of the device and the port number.
I need to send it a 6 byte command: example
0xFD,Ox2,020,1,0,0x5d
This command will tell Relay 1 to turn on.
0xFD,Ox2,020,1,1,0x5d
This command will tell Relay 1 to turn off.
Any help with this would be greatly appreciated Thank you!
I think you may want to check out fsockopen
You can do something like:
$socket = fsockopen($ip, $port);
if($socket) {
fwrite($socket, $string);
}
Instead of building an ASP web site just to turn on/off the device, you can simply create a very simple HTML page with 2 buttons (ON and OFF). If you put this page on the network, it can be opened by any browser.
Assuming that your command string is processed as an URL, the Javascript functions executed when clicking on a button would call the following procedure:
function httpGet(theUrl)
{
var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", theUrl, false );
xmlHttp.send( null );
return xmlHttp.responseText;
}
If the device is controlled by TCP/IP, you may need to code some C# functions, unless using a utility allowing to send data to TCP/IP (example "Packet sender").
I have a client which GETs a JSON response from a server. I want to calculate how many requests/responses will consume my allotted transfer allowance from a web hosting company (e.g. 100GB per month).
How do I measure/calculate this?
I assume I only need to measure once because the msgs are of a consistent length and format.
I have control over client/server/network. All can be uniquely dedicated to the task. The client is an IOS App and the server is a PHP REST Web Service (on Windows). Both on my LAN.
I know nothing about this and so far have just got the size of the JSON using strlen(). Is that even heading in the right direction?
I would recommend using Charles Proxy. It is an invaluable tool for debugging all kinds of information exchanged via HTTP. You may use it for tracing all HTTP/s communication from and to your iPhone/iPod/iPad as well as the simulator.
It does unfortunately not work too well with most Android devices as those do not really support configuring a system-wide HTTP proxy. For those cases and non HTTP-based communication, I would recommend using WireShark.
In some rare cases, for reasons that are still unclear to me, Charles rarely fails on iOS devices for HTTP-based connections - a typical case would be GoogleAnalytics. For those, again I would recommend WireShark.
The length of JSON string gives you only the size of the payload field in the transferred network packets. This data field may be encapsulated within an HTTP packet and HTTP packet should be put into an IP packet before transmission. Each of these packets have header fields which contributes to total transmission length.
So, for a precise estimate you should first find the real length of the response packet by using Wireshark or an equivalent tool. If this is the only request type for your application you can divide your bandwidth to the response size of your server application to get maximum number of requests to reach the limit. However, this is usually not the case if you have a web application which has several web pages that are accessible from clients, since any access (browsing) will cause a data transfer from server to client.
Your Apache logs will have the number of bytes of each request, but assuming you want a completely PHP solution, add this to the beginning of your scripts:
<?php
function log_input() {
# get raw post data
$length = strlen(file_get_contents('php://input'));
if (function_exists('apache_request_headers')) {
# quick, but not accurate
$length += strlen(serialize(apache_request_headers()));
} else {
# add fudge for HTTP/1.1 etc
$length += strlen($_SERVER['QUERY_STRING']) + 14;
foreach ($_SERVER as $k => $v) {
if (preg_match('/^HTTP/i', $k)) {
$length += strlen($k) + strlen($v);
}
}
}
$s = sprintf("%s\t%s\n", date('c'), $length);
file_put_contents('/tmp/input.log', $s, FILE_APPEND);
}
function log_output() {
$s = sprintf("%s\t%s\n", date('c'), ob_get_length());
file_put_contents('/tmp/output.log', $s, FILE_APPEND);
}
log_input();
register_shutdown_function('log_output');
ob_start();
?>
<html> ....
What does it mean, when an in-browser websocket object receives a onmessage event with the message data length equal to 0?
specifically I use Safari as websocket client (Hixie). The client code is nothing special.
socket = new WebSocket(host);
socket.onmessage = function(msg)
{
log("Received: "+msg.data.length);
if(msg.data.length > 0) ... processing
};
The server is based on PHP, and messages are sent without errors.
I think this is just a Safari annoyance. The current released versions of Safari implement the older WebSockets protocol version and the implementation works but it is a bit lacking. The 0 length messages issue is pretty tame. A more serious issue is the inability to properly close a connection (basically doesn't close the actual socket until the page is reloaded).
Try the same test with a recent Chrome. If you don't see the problem there then it's just a Safari issue. If you still see 0 length messages, then it is likely that the PHP websocket server is sending 0 length messages (perhaps as a sort of poor man keep-alive).
I have a web service written in PHP to which an iPhone app connects to. When the app calls the service, a series of notification messages are sent to Apple's APNs server so it can then send Push Notifications to other users of the app.
This process can be time consuming in some cases and my app has to wait a long time before getting a response. The response is totally independent of the result of the notification messages being sent to the APNs server.
Therefore, I would like the web service to send the response back to the app regardless of whether the messages to APNs have been sent.
I tried using pcntl_fork to solve the problem:
<?php
...
$pid = pcntl_fork();
if($pid == -1)
{
// Could not fork (send response anyway)
echo "response";
}
else if($pid)
{
// Parent process - send response to app
echo "response";
}
else
{
// Child process - send messages to APNs then die
sendMessageAPNs($token_array);
die();
}
?> // end of script
Unfortunately, the parent process seems to wait for the child process to end before sending the response even though I do not use pcntl_wait in the parent process. Am I doing something wrong or is this normal behaviour? If this is normal then is there another way I can solve this problem?
Thank you!
If you're hosting the PHP process in Apache then you really shouldn't use this: see this for the section that says *Process Control should not be enabled within a web server environment and unexpected results may happen if any Process Control functions are used within a web server environment. *.
You should probably set up a separate daemon in your preferred language of choice and hand the APNS communication tasks off to that. If you really really really must try using ob_flush().
I think you can send the response back before doing the "long" process. Take a look at the flush() function of PHP it'll maybe help