Im kinda new with the sockets stuff and Im trying to make a server on PHP to support websockets calls from my javascript currently my code looks like this
<?php
class Websocket
{
private $server;
private $sockets = [];
public function create($host)
{
$this->server = stream_socket_server('tcp://localhost:8080', $errno, $errmsg);
stream_set_blocking($this->server, 0);
}
public function run()
{
while(true)
{
$client = stream_socket_accept($this->server);
if($client)
{
$data = stream_socket_recvfrom($client, 2048);
if($data)
{
echo 'Client connected'.PHP_EOL;
echo $data;
$response = $this->handshake($data);
stream_socket_sendto($client, $response);
}
}
}
}
private function handshake($data)
{
$data = explode(PHP_EOL, $data);
foreach($data as $header)
{
$current_header = explode(':', $header);
if($current_header[0] == 'Sec-WebSocket-Key')
{
$accept = base64_encode(sha1(trim($current_header[1]).'258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));
$response = 'HTTP/1.1 101 Switching Protocols'.PHP_EOL.'Upgrade: websocket'.PHP_EOL.'Connection: Upgrade'.PHP_EOL.'Sec-WebSocket-Accept:'.$accept.PHP_EOL.PHP_EOL;
return $response;
}
}
}
}
And my javascript is just a simple
var socket = new WebSocket('ws://localhost:8080');
socket.onopen = function(event)
{
console.log('connected');
socket.send('hello');
}
Currently the message connected appears on my chrome console but after that when the hello message is supposed to be sent I get this error
"connection to: xxx was interrupted while the page was loading"
So my question is after I have successfully send the handshake to the client how do I process messages? I know my code is always sending the handshake to new connections but on my server I will only see the first message beeing echoed (the http request) and not the "hello" one
You need to handle the message -
socket.onmessage = function(e){
var server_message = e.data;
console.log(server_message);
}
Related
So currently, I manage to communicate between php and java thanks to the socket. The problem is that once the java client is connected, I can't do anything anymore.
I would like that when a js event is triggered, information to the java client is transmitted.
How can I do that?
Thanks
My code php:
$host = "0.0.0.0";
$port = 6969;
set_time_limit(0);
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Create Error");
$result = socket_bind($socket, $host, $port) or die("Bind Error");
$result = socket_listen($socket, 3) or die("Listener Error");
$spawn = socket_accept($socket) or die("Accept Error");
$input = socket_read($spawn, 1024) or die("Read Error");
echo "Received: ".$input;
$output = "Received";
socket_write($spawn, $output, strlen($output)) or die("Write Error");
My java code:
Socket socket = new Socket("localhost", 6969);
PrintWriter writer = new PrintWriter(socket.getOutputStream());
writer.println("Test Message");
writer.flush();
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println(reader.readLine());
I will suggest you to use REST unless you have a very specific use case .
Else you need to close socket (on client * php ) and stream once you get the data.
https://docs.oracle.com/javase/tutorial/networking/sockets/readingWriting.html
read the explanation here, this will help you
I'm learning WebSocket using PHP library Ratchet. But I have a problem sending the message from client/browser. I have tried using chrome and firefox.
The message is not sent to the server until I disconnect the client by closing the tab or refresh the browser.
Update: My server use Centos 7 with firewalld enabled.
After I close the browser tab, the server output is like this:
Connection 73 sending message "tes" to 1 other connection
Connection 73 has disconnected
Here is the javascript code:
conn = new WebSocket('ws://websocket.develop.local:8080');
conn.onopen = function(e) {
console.log("Connection established!");
};
conn.onmessage = function(e) {
console.log('ada message');
console.log(e.data);
};
conn.onerror = function(e) {
console.log("WebSocket Error: " , e);
//Custom function for handling errors
//handleErrors(e);
};
function sendMessage(){
var message = document.getElementById("pesan").value;
conn.send(message);
console.log('Sending message: ' + message);
};
And here is the PHP code (I got this from Ratchet docs):
<?php
namespace MyApp;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
class Chat implements MessageComponentInterface {
protected $clients;
public function __construct() {
$this->clients = new \SplObjectStorage;
}
public function onOpen(ConnectionInterface $conn) {
// Store the new connection to send messages to later
$this->clients->attach($conn);
echo "New connection! ({$conn->resourceId})\n";
}
public function onMessage(ConnectionInterface $from, $msg) {
$numRecv = count($this->clients) - 1;
echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n"
, $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');
foreach ($this->clients as $client) {
if ($from !== $client) {
// The sender is not the receiver, send to each client connected
$client->send($msg);
}
}
}
public function onClose(ConnectionInterface $conn) {
// The connection is closed, remove it, as we can no longer send it messages
$this->clients->detach($conn);
echo "Connection {$conn->resourceId} has disconnected\n";
}
public function onError(ConnectionInterface $conn, \Exception $e) {
echo "An error has occurred: {$e->getMessage()}\n";
$conn->close();
}
}
Here is the premise of what I'm doing:
I have a program running in the background, a socket server, at all times.
I created a website that calls a php script (using AJAX) that opens a client side socket, connects to the server, sends the request and receives it, then echos it out.
This echo is the response is the 'return value' for my AJAX script.
This is this issue:
When I click a button, the information sends but, sometimes, the information never makes it back to the site.
I know the request is being processed through the server because I can see the request running to completion on the server side.
I know that the information from the server side is sending to the client (the website) because I have a code that checks if data was successfully sent from the server side.
Sometimes the request is sent through and the appropriate response client side (an alert pop-up with information from the server) comes through.
Website Code:
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="POST">
<input type="submit" class="button" name="weather" value="weather" />
<input type="submit" class="button" name="time" value="time" />
<input type="submit" class="button" name="date" value="date" />
</form>
jQuery Code:
$(document).ready(function(){
$('.button').click(function(){
var clickBtnValue = $(this).val();
var ajaxurl = 'php/portserverclient.php',
dataSend = {'action': clickBtnValue};
$.post(ajaxurl, dataSend, function (response) {
// Response div goes here.
//$('#servermessage').val($('#servermessage').val()+response);
alert(response);
});
});
PHP Code:
<?php
// -------------------------------------
// ----- Get Information Sent from Site
// -------------------------------------
if (isset($_POST['action']))
{
switch ($_POST['action']) {
case 'weather':
$in = "3";
$request = "Weather";
break;
case 'time':
$in = "2";
$request = "Time";
break;
case 'date':
$in = "1";
$request = "Date";
}
}
else
{
$in = "3";
$request = "Weather";
}
// -------------------------------------
// ----- Open Client Side Socket
// -------------------------------------
error_reporting(E_ALL);
$A1 = "Starting TCP/IP Connection... \n";
/* Get the port for the WWW service. */
$service_port = 51713;
/* Get the IP address for the target host. */
$address = '192.168.8.129';
/* Create a TCP/IP socket. */
$socket = socket_create(AF_INET, SOCK_STREAM, 0);
if ($socket === false)
{
$A2 = "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
exit;
}
else {
$A2 = "Socket Created...OK.\n";
}
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec' => 5, 'usec' => 0));
socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array('sec' => 5, 'usec' => 0));
$A3 = "Attempting to connect to '$address' on port '$service_port'...";
$result = socket_connect($socket, $address, $service_port);
if ($result === false)
{
$A4 = "socket_connect() failed.\nReason: ($result) " . socket_strerror(socket_last_error($socket)) . "\n";
exit;
}
else
{
$A4 = "OK.\n";
}
// -------------------------------------
// ----- Send message through socket
// -------------------------------------
$A5 = "Sending $request request...";
$sent = socket_write($socket, $in, strlen($in));
$A6 = "OK.\n";
// -------------------------------------
// ----- Receive response through socket
// -------------------------------------
$out = ' ';
do{$out = socket_read($socket, 20, PHP_NORMAL_READ) ;}
while($out === false);
// -------------------------------------
// ----- Close Client Side Socket
// -------------------------------------
$A7 = "Closing socket...";
$A8 = "OK.\n";
echo "\n From PHP END: ", $A1,$A2,$A3,$A4,$A5,$A6,$A7,$A8,"Message: ", $out,"\n";
socket_shutdown($socket,2);
socket_close($socket);
exit;
?>
C++ Server Side Code:
//---- read buffer ---
sizeofread = read(newsockfd, msg, 20);
if (sizeofread <= 0 || msg[0] == 0x0A || msg[0] == 0x0D || msg[0] == 0x00)
{
// Stops any buggy send (size of read <= 0)
// Stops terminal from sending new line (0x0A & 0x0D) after each press enter
// Stops terminal from sending 0 constantly (0x00)
}
else
{
printf("Received from TCP: %s \n",msg);
//--- Send to Arduino ---
printf( "Sending to Arduino: %s \n", msg);
write( uartt, msg, 20 );
delay(50); // Here to account for how long it takes to send & receive 20 bytes at 9600 Baud
//--- Receive from Arduino ---
while (counter <= 2 && found == false)
{
if ( !( msgLength = serialDataAvail(uartt) ))
{
printf("Nothing to read \n");
delay(1071); // Here to account for how long it takes to receive 1024 bytes at 9600 Baud
counter++;
}
else
{
found = true;
read(uartt, msg, msgLength);
msg[msgLength] = 0;
if (write(newsockfd, msg, 20) < 0)
{
printf("Failed to send to socket \n");
}
else
{
printf("Succesfully sent to socket \n");
}
printf("From the Arduino: ");
printf("%s \n", msg);
}
delay(100);
serialFlush(uartt);
}
counter = 0;
found = false;
close(newsockfd);
goto repeat;
}
Turns out the answer to this riddle was that I needed to disable the Submit buttons default event. Normally, in HTML, the submit button refreshes the page, this must be stopped.
It was stopped like this:
$('.button').click(function(event){
var clickBtnValue = $(this).val();
var ajaxurl = 'php/portserverclient.php',
dataSend = {'action': clickBtnValue};
$.post(ajaxurl, dataSend, function (response) {
alert(response);
});
event.preventDefault();
});
Thanks guys
I am new in websockets technology. I was trying to create a websockets php server and connect to the server with a javascript client. I am using xampp 1.8.3.
I made this simple PHP server:
<?php
error_reporting(E_ALL);
set_time_limit(0);
$address = "127.0.0.1";
$port = 1777;
$maxConnections = 10;
if(!($sock = socket_create(AF_INET, SOCK_STREAM, 0))){
$errorCode = socket_last_error();
$errorMsg = socket_strerror($errorCode);
die("socket_create() failed -> {$errorCode}:{$errorMsg}\n");
}
echo "Server created.\n";
if(!(socket_bind($sock, $address, $port))){
$errorCode = socket_last_error();
$errorMsg = socket_strerror($errorCode);
die("socket_bind() failed -> {$errorCode}:{$errorMsg}\n");
}
echo "Server opened on {$address}:{$port}\n";
if(!(socket_listen($sock, $maxConnections))){
$errorCode = socket_last_error();
$errorMsg = socket_strerror($errorCode);
die("socket_listen() failed -> {$errorCode}:{$errorMsg}\n");
}
echo "Waiting for connections...\n";
$client = socket_accept($sock);
if(socket_getpeername($client, $address, $port)){
echo "The client {$address}:{$port} is online.\n";
}
$msg = socket_read($client, 1024000);
if(!(socket_write($client, $msg, strlen($msg)))){
$errorCode = socket_last_error();
$errorMsg = socket_strerror($errorCode);
die("socket_write() failed -> {$errorCode}:{$errorMsg}\n");
}
echo "Message sent\n";
socket_close($client);
socket_close($sock);
?>
I ran this php file with xampp shell using the following expression:
php htdocs/server.php
and I got this message on shell:
php htdocs/server.php
Server created.
Server opened on 127.0.0.1:1777
Waiting for connections...
Then I opened my client.html on chrome (my supports websockets).
My client.html code is:
<html>
<head>
<meta charset="UTF-8" />
<title>Websockets web-server connection</title>
</head>
<body>
<p>Websockets connection. Status: <span id="status"></span></p>
<script type="text/javascript">
var webSockets = new WebSocket("ws://127.0.0.1:1777/");
webSockets.onopen = function(){
document.getElementById("status").innerHTML="connected";
webSockets.send("ping");
}
</script>
</body>
</html>
And I received this message on javascript console log:
WebSocket connection to 'ws://127.0.0.1:1777/' failed: client.html:9
And my shell had this messages:
php htdocs/server.php
Server created.
Server opened on 127.0.0.1:1777
Waiting for connections...
The client 127.0.0.1:64446 is online
Message sent
However I didn't receive any message on client, I do not even get a connected status.
What is happening? Where is my error?
Thank you.
WebSockets are not raw TCP sockets. They require a rather complex HTTP-like handshake to establish a connection, and require data transferred over them to be encoded and framed in a very particular way. The protocol is defined in RFC 6455.
Unless you are feeling incredibly masochistic, you don't want to try to implement this yourself. Use a library like Ratchet to implement WebSockets in PHP.
I had the same problem bro but no need of using Ratchet or other libraries you can write your own simple code . The handshake process,and the masking-unmasking of messages is rather difficult so i copied the code for those
function perform_handshaking($receved_header,$client_conn, $host, $port)
{
$headers = array();
$lines = preg_split("/\r\n/", $receved_header);
foreach($lines as $line)
{
$line = chop($line);
if(preg_match('/\A(\S+): (.*)\z/', $line, $matches))
{
$headers[$matches[1]] = $matches[2];
}
}
$secKey = $headers['Sec-WebSocket-Key'];
$secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
//hand shaking header
$upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"WebSocket-Origin: $host\r\n" .
"WebSocket-Location: ws://$host:$port/\r\n".
"Sec-WebSocket-Accept:$secAccept\r\n\r\n";
socket_write($client_conn,$upgrade,strlen($upgrade));
return $upgrade;
}
function unmask($text) {
$length = ord($text[1]) & 127;
if($length == 126) {
$masks = substr($text, 4, 4);
$data = substr($text, 8);
}
elseif($length == 127) {
$masks = substr($text, 10, 4);
$data = substr($text, 14);
}
else {
$masks = substr($text, 2, 4);
$data = substr($text, 6);
}
$text = "";
for ($i = 0; $i < strlen($data); ++$i) {
$text .= $data[$i] ^ $masks[$i%4];
}
return $text;
}
//Encode message for transfer to client.
function mask($text)
{
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);
if($length <= 125)
$header = pack('CC', $b1, $length);
elseif($length > 125 && $length < 65536)
$header = pack('CCn', $b1, 126, $length);
elseif($length >= 65536)
$header = pack('CCNN', $b1, 127, $length);
return $header.$text;
}
Instead of socket_accept user socket_read to get the http header containing request from webpage that it wants to upgrade its http conn to websocket then use the handshake function above to write an accept header message .then your connection will be established .but still on the client side you have to add events like these
if("WebSocket" in window){
var a = "ws://"+serverip+":9000";
var ws = new WebSocket(a);
var error = null;
ws.onopen = function(){
open();
}
ws.onerror = function(err){
errorhandler(err);
}
ws.onmessage = function(e){
messagehandler(e);
}
ws.onclose = function(){
close();
}
}
function open(){
document.getElementById('logs').innerHTML+='<p>WebSocket Connection OPened</p>';
}
function errorhandler(err){
document.getElementById('logs').innerHTML+='<p>WebSocket Connection Error occured  '+err.data+'</p>';
}
function messagehandler(a){
document.getElementById('logs').innerHTML+="<p>"+a.data+"</p>";
}
function close(){
document.getElementById('logs').innerHTML+='<p>WebSocket Connection Closed</p>';
ws = null;
}
I'm trying to create a simple WebSocket example using the HTML5/JS API. Based on what I trace out on the server, it seems like the socket is connecting, but none of the events fire (onopen, onmessage, onclose, etc). I'm a Flash developer so I'm not very good at debugging the JavaScript and I'm hoping someone can help me out. Here's the client side code I'm using:
<script type="text/javascript" charset="utf-8">
function startSocket()
{
if("WebSocket" in window)
{
var ws = new WebSocket("ws://localhost:1740");
ws.onopen = function() {
window.alert("open!");
}
ws.onmessage = function(event) {
window.alert(event.data);
}
ws.onclose = function() {
window.alert("Closed");
}
ws.onerror = function() {
window.alert("trouble in paradise");
}
}
}
</script>
And here's my socket server code (which works just fine from Flash, but that may not mean anything):
<?php
create_connection('localhost',1740);
function create_connection($host,$port)
{
$socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
if (!is_resource($socket)) {
echo 'Unable to create socket: '. socket_strerror(socket_last_error()) . PHP_EOL;
} else {
echo "Socket created.\n";
}
if (!socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1)) {
echo 'Unable to set option on socket: '. socket_strerror(socket_last_error()) . PHP_EOL;
} else {
echo "Set options on socket.\n";
}
if (!socket_bind($socket, $host, $port)) {
echo 'Unable to bind socket: '. socket_strerror(socket_last_error()) . PHP_EOL;
} else {
echo "Socket bound to port $port.\n";
}
if (!socket_listen($socket,SOMAXCONN)) {
echo 'Unable to listen on socket: ' . socket_strerror(socket_last_error());
} else {
echo "Listening on the socket.\n";
}
while (true)
{
$connection = #socket_accept($socket);
if($connection)
{
echo "Client $connection connected!\n";
send_data($connection);
} else {
echo "Bad connection.";
}
}
}
function send_data($connection)
{
echo $connection;
// Create a number between 30 and 32 that will be our initial stock price.
$stock_price = rand(30,32);
while (true)
{
socket_write($connection,"$stock_price\n",strlen("$stock_price\n"));
sleep(1);
// Generate a random number that will represent how much our stock price
// will change and then make that number a decimal and attach it to the
// previous price.
$stock_offset = rand(-50,50);
$stock_price = $stock_price + ($stock_offset/100);
echo "$stock_price\n";
}
}
?>
Are you calling startSocket() somewhere else in your code?
I know this code works. You might be able to adapt it: http://github.com/dshaw/zombo-socket/blob/master/zombocom-client.html
Maybe this is completely obvious, but if anyone else gets this, the problem is that you need to add a handshake. In Flash this isn't required and I still don't fully understand it, but I was able to modify this project - http://code.google.com/p/phpwebsocket/ - and it worked as it was supposed to by adding the gethandshake code after my socket_accept code ran.