Im am trying to implement push integration using php and native zmq. I have successfully send send my message to server, but my problem is I cannot push the message to browser using js Websocket(). I says WebSocket connection to 'ws://127.0.0.1:8080/' failed: Error during WebSocket handshake: Invalid status line
here is my code for client:
<?php
try {
function send($data) {
$context = new ZMQContext();
$push = new ZMQSocket($context, ZMQ::SOCKET_PUSH);
$push->connect("tcp://localhost:5555");
$push->send($data);
}
if(isset($_POST["username"])) {
$envelope = array(
"from" => "client",
"to" => "owner",
"msg" => $_POST["username"]
);
send(json_encode($envelope)); # send the data to server
}
}
catch( Exception $e ) {
echo $e->getMessage();
}
?>
Client
here is my server:
$context = new ZMQContext();
$pull = new ZMQSocket($context, ZMQ::SOCKET_PULL);
$pull->bind("tcp://*:5555"); #this will be my pull socket from client
$push = new ZMQSocket($context, ZMQ::SOCKET_PUSH);
$push->bind("tcp://127.0.0.1:8080"); # this will be the push socket to owner
while(true) {
$data = $pull->recv(); # when I receive the data decode it
$parse_data = json_decode($parse_data);
if($parse_data["to"] == "owner") {
$push->send($parse_data["msg"]); # forward the data to the owner
}
printf("Recieve: %s.\n", $data);
}
and here is my owner.php i'm expecting the data to be send thru Websocket in browser:
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h2>Message</h2>
<ul id="messagelog">
</ul>
<script>
var logger = document.getElementById("messagelog");
var conn = new WebSocket("ws://127.0.0.1:8080"); # the error is pointing here.
conn.onOpen = function(e) {
console.log("connection established");
}
conn.onMessage = function(data) {
console.log("recieved: ", data);
}
conn.onError = function(e) {
console.log("connection error:", e);
}
conn.onClose = function(e) {
console.log("connection closed~");
}
</script>
</body>
Please do tell me what I am missing. thank you.
You didn't establish a protocol communication at all. You managed to receive the message, but you never confirmed, by parsing it and sending appropriate response, that your server is indeed a WebSocket server.
Since you are already using PHP and ZeroMQ, the easiest way out is to use Mongrel2 which is, among other things, capable of understanding WebSocket protocol and deliver it to a ZeroMQ endpoint encoded as a tnetstring (a json-like encoding format, trivial to parse).
The other solution is to fully support the WebSocket protocol in your code - something that's outside of the scope of this question and answer.
You cannot connect a websocket to a zmq socket*, they are different communication protocols (a websocket is more like a traditional socket, a zmq socket is more of an abstraction that adds extra features). You need to set up a way on your server to receive a websocket connection.
*You may be able to make this work using RAW socket types, but that's a bit more advanced and shouldn't be entered into unless you know what you're doing.
Related
I am developing a project, a wordpress plugin. And I have to do instant transactions, so I wanted to use websocket instead of ajax.I run node.js with socket.io on my server server now everything goes well. But how do I send the data coming to the node.js server to php? I ran an ajax query for this, on the node.js side, how correct is this usage. I also tried some derivatives such as elephant.io and I couldn't send data to socket.io with php.
I've been searching for almost 2 days, but the sources I found are always old and I could not come to a conclusion so I decided to ask here.
How do I transfer the data sent from the client to node.js to php and get the returned data.
How do I send data from PHP to socket.io or socket.io to PHP?
Is it logical to send the data sent from the client via websocket to the php page with ajax in node.js?
In fact, the 3 questions I ask are in the same place, except for the basic differences, can you help me with this?
Yes, I can now send data to the client with a php page. But how do I capture the data from the client here.
require __DIR__ . '/vendor/autoload.php';
use ElephantIO\Client;
use ElephantIO\Engine\SocketIO\Version2X;
$client = new Client(new Version2X('http://localhost:3000'));
$client->initialize();
$client->emit('server_way', ['foo' => 'bar']);
$client->close();
if ( isset( $_GET['action'] ) ) {
echo $_GET['action'];
}
const ajax_url = 'http://localhost/projeler/bp-instant-message-socket-io-core/socket.php';
const http = require('http').createServer();
const io = require('socket.io')(http,{
cors: {
origin: "http://localhost",
methods: ["GET", "POST"]
}
});
var $ = require('jquery')(require('jsdom-no-contextify').jsdom().parentWindow);
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
$.support.cors = true;
$.ajaxSettings.xhr = function () {
return new XMLHttpRequest;
}
io.on('connection', (socket) => {
console.log("biri bağlandı");
socket.on('server_way', (data) => {
console.log(data);
io.emit('client_way',data);
});
socket.on('disconnect',function(){
console.log("biri ayrıldı");
});
});
http.listen(3000, () => {
console.log('listening on *:3000');
});
I'm trying to make a watchlist for cryptocurrency tickers You type a ticker, add it, and it will show you real time prices in a table format.
My first step is to try and establish a handshake connection with the Kraken websocket API (documentation here: https://www.kraken.com/features/websocket-api#connectionDetails)
My ask:
At the moment, all I want to do is be able to console log a "connection success" for when I'm connected with the websocket API from Kraken (crypto exchange). I'm trying to do this via the portion below (scroll all the way down to see all of the code)
socket.onopen = function(event) {
socketStatus.innerHTML = 'Connected to: ' + event.currentTarget.url;
socketStatus.className = 'open';
};
I've got an index.html file, and an app.js file. When I open the index.html file in chrome, I get an error:
app.js:5 WebSocket connection to 'ws://ws-sandbox.kraken.com/' failed: Error during WebSocket handshake: Unexpected response code: 521
I've tried with only this line of code for websocket related stuff
var socket = new WebSocket('ws://ws-sandbox.kraken.com')
I've also tried to use the get method, provided in examples from here
https://medium.freecodecamp.org/here-is-the-most-popular-ways-to-make-an-http-request-in-javascript-954ce8c95aaa
$.get('ws://ws-sandbox.kraken.com',function(data){console.log(`${data}`)})
in my app.js file, my question is, apart from line below what else do I need to successfully do the handshake? Do I need to send a GET request with header information (please see very end)?
var socket = new WebSocket('ws://ws-sandbox.kraken.com')
in the documentation, you'll see connection details. Connection details for sandbox environment. The URL is ws-sandbox.kraken.com
link: https://www.kraken.com/features/websocket-api#connectionDetails
I've followed the example here:
https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
GET REQUEST QUESTION:
I was looking at this site as an example:
https://blog.teamtreehouse.com/an-introduction-to-websockets
and it said I need to send an HTTP request to the server using something similar to this. I'm just not sure if this is required for what I'm trying to do.
GET ws://websocket.example.com/ HTTP/1.1
Origin: http://example.com
Connection: Upgrade
Host: websocket.example.com
Upgrade: websocket
CODE IN APP.JS FILE
$(document).ready(function(){ console.log('page ready')
var socket = new WebSocket('ws://ws-sandbox.kraken.com')
$.get('ws://ws-sandbox.kraken.com',function(data){console.log(`${data}`)})
var form = document.getElementById('message-form');
var messageField = document.getElementById('message');
var messagesList = document.getElementById('messages');
var socketStatus = document.getElementById('status');
var closeBtn = document.getElementById('close');
socket.onopen = function(event) { //LOGGING SUCCESSFUL CONNECTION HERE
socketStatus.innerHTML = 'Connected to: ' + event.currentTarget.url;
socketStatus.className = 'open';
};
})
I know this is an old question but I was having the same issue and wanted to provide my solution in case anyone else comes here in need of it.
So the reason I found for this error was because I using a protocol that was not supported by the API. I was using TLS 1.0 where the Kraken API only supports 1.2/1.3:
https://support.kraken.com/hc/en-us/articles/360023264371-TLS-upgrade-that-might-affect-your-API-connections
So to solve it, I simply set my websocket client to use TLS 1.2 as the protocol.
From a browser, using the Websocket() built-in api:
new WebSocket("wss://ws.kraken.com").onopen = function(){
this.onclose = () => console.log("SOCKET CLOSED")
this.onmessage = (e) => console.log(JSON.parse(e.data))
this.send(JSON.stringify({
"event": "subscribe",
"pair": ["XBT/USD"],
"subscription": {
"interval": 1,
"name": "ohlc"
}
}), (e) => console.log(e))
}
I am currently connecting to an external XMPP server (not mine). Since I couldn't find any XMPP PHP client which suits my needs, I have developed my own simple client (XMPP PHP). The client opens a socket connection to the server and that is where the XML exchange happens, and that part works well.
The main reason for developing this package was to integrate it within a corporate app. I have done so and can successfully send messages back and forth.
Even though my end goal is to have an open websocket connection, currently the program works by polling the server in 2s interval (I am using a simple 1on1 communication, no chat rooms or similar):
receiveMessages: function () {
this.poll = setInterval(function () {
Ext.Ajax.request({
url : 'index.php',
method : 'post',
params : {
method: 'receiveMessages',
},
scope : this,
callback: function (options, success, response) {
...
}
});
}, this.pollTimer);
}
And on the PHP side:
public function receiveMessages()
{
$messages = $this->client->getMessages();
if ($messages) {
foreach ($messages as $message) {
$message = $this->xml2array($message);
$conversation = $this->conversationExists($message['#attributes']['from']);
if ($conversation == null) {
$preparedConversation = array(
...
);
$conversation = $this->_save($preparedConversation ...);
}
$message = array(
...
);
$response = $this->_save($message ...);
return array(
'success' => true,
'response' => $response,
);
}
}
}
Upon success, this method updates frontend with the received message, as well as saves the message to the DB. DB is organized in a way that one User can have many Conversations and one Conversation can have many Messages.
What I fail to understand though is how should everything be structured in order to function like some of the real chat clients (Facebook or other messengers), because this way I can't get the "concurrency" I want. If I log in with my account on 2 different places, each of them will poll the server every 2s, and it is basically a race condition, first one to get the message will display it.
If I think about it, one way to do it properly would be to implement websockets to server, and have frontend wait for DB changes, however I think this may create much read overhead on DB. Can someone give me some advice on how to do this?
So I am trying to make some sort of connection between my Java app and my Web app, I looked up websockets and they look really simple and easy to use :). And I created myself a Java Server, which uses the ServerSocket class.
Now the problem is I am able to connect to the server from the web, with the websocket, but I am unable to send data to the server... but when I tried to send data from a Java Client it worked fine... what might be the problem?
My Java/Scala (I followed this tutorial: https://www.tutorialspoint.com/java/java_networking.htm) server:
class Server(val port: Int) extends Thread {
private val serverSocket = new ServerSocket(port)
override def run(): Unit = {
try {
while(true) {
println("Waiting for client on port: " + serverSocket.getLocalPort)
val server = serverSocket.accept()
println(server.getRemoteSocketAddress)
val in = new DataInputStream(server.getInputStream())
println(in.readUTF())
val out = new DataOutputStream(server.getOutputStream())
out.writeUTF("Hello world!")
server.close()
}
} catch {
case s: SocketTimeoutException => println("Connection timed out!");
case e: Exception => e.printStackTrace()
}
}
}
My web js (I followed https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications ):
/**
* Created by samuelkodytek on 20/12/2016.
*/
var conn = new WebSocket('ws://127.0.0.1:8080');
conn.onopen = function(e) {
console.log("Connection established!");
conn.send("Hello!");
};
conn.onmessage = function(e) {
console.log(e.data);
};
A web socket server is not the same thing as a simple socket server. A server that offers web sockets must first offer HTTP or HTTPS services because the web socket is established when a web client sends an HTTP request with an Upgrade option and special fields for establishing the web socket. Even after the web socket is established, the connection still does not behave exactly like a regular socket. The Web Socket protocol uses frames to send or receive data. This is all considerably different from what you seem to expect.
One other thing that you should be aware of is that the browser will enforce the rule that the web socket must come from the same host as the page that is attempting to establish the web socket (the same protocol, address, and TCP port).
When I set up a websocket connection from JavaScript, how can I authorize that it is a legit user on the serverside? I am using JSON Web Tokens and when doing regular calls to REST backend I automatically add an Authorization: Bearer (JWT..) header on AngularJS and then check that on the server side to see if a user is logged in. How can I do that when upgrading the connection to a websocket connection? I am afraid that some people with connect to the server requesting a websocket connection and spoof some of the users id's and receive their messages without being logged in to the service.
I request a websocket connection like this:
var conn = new WebSocket("ws://localhost:8080/api/ws");
conn.onclose = function (e) {
console.log("disconnected");
};
conn.onopen = function (e) {
console.log("connected");
};
conn.onmessage = function (e) {
console.log(e.data);
};
On the first part, is that a GET request or a POST request? Can I add parameters to the url and check them on the serverside? For example:
var conn = new WebSocket("ws://localhost:8080/api/ws/token/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ");
Or is this not a good idea? I also thought sending a JWT would be a good idea because I would be able to extract the user_id from the JWT and associate a websocket connection to a specific user.
How can I solve this problem?