I have stumbled upon a issue successfully enabling a web socket connection between the web browser, and the Yaws web server.
Both, the Javascript code sample by the client, and Erlang code samples by the server that I want to show came from samples in a programming textbook called, "Building Web Applications with Erlang".
I have a feeling that the issue is I'm running a later version of the Yaws Web server than this book, "2.0.6" to be exact; but I don't know. I want to know your thoughts. Thank you.
Javascript code sample (Client side).
$(function ()
{
var WebSocket = window.WebSocket || window.MozWebSocket;
var socket = new WebSocket("ws://localhost:8080/");
// wait for socket to open
socket.onopen = function ()
{
$('input#echo').on('keypress', function (event)
{
if (event.which == 13) {
event.preventDefault();
var msg = $(this).val();
socket.send(JSON.stringify(
{
message:msg
}
));
}
});
socket.onmessage = function(msg)
{
var message = $.parseJSON(msg.data);
var html = $('div#messages').html() + message.message + "<br>\n";
$('div#message').html(html);
}
}
});
Upgrade: WebSocket
Erlang code sample (server-side)
-module(sole_callback).
%% Export for websocket callbacks
-export([handle_message/1, say_hi/1]).
handle_message({binary, Message}) ->
io:format("~p:~p basic echo handler got ~p~n",
[?MODULE, ?LINE, Message]),
{reply, {binary, <<Message/binary>>}}.
say_hi(Pid) ->
io:format("asynchronous greetings~n", []),
yaws_api:websocket_send(Pid, {text, <<"hi there!">>}).
Erlang code sample (Embedded mode)
<script language="Javascript" type="text/javascript" src="jquery.min.js"></script><script language="Javascript" type="text/javascript" src="record.js"></script><script language="Javascript" type="text/javascript" src="socket.js"></script>
<erl>
out(Arg) ->
{html, "<img src=images_folder/audio.png onclick=socket.onopen() width=25px height=25px>"}.
</erl>
<erl>
get_upgrade_header(#headers{other=L}) ->
lists:foldl(fun({http_header,_,KO,_,V}, undefined) ->
K = case is_atom(KO) of
true ->
atom_to_list(KO);
false ->
KO
end,
case string:to_lower(K) of
"upgrade" ->
true;
_ ->
false
end;
(_, ACC) ->
ACC
end, undefined, L).
%%------------------------------------------------------------------------------
out(Arg) ->
case get_upgrade_header(Arg#arg.headers) of
true ->
error_logger:warning_msg("Not a web socket client~n"),
{content, "text/plain", "You're not a web sockets client! Go away!"};
false ->
error_logger:info_msg("Starting web socket~n"),
{websocket, sole_callback, []}
end.
</erl>
Related
We are trying to listen to the kafka topics using js code from browser once the Producer from server side pushes messages to the particular kafka topic.
In the server side, kafka server and zookeeper are running at 9092 and 2181 port respectively.
String topicName = "test";
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("acks", "all");
props.put("retries", 0);
props.put("batch.size", 16384);
props.put("linger.ms", 1);
props.put("buffer.memory", 33554432);
props.put("key.serializer",
"org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer",
"org.apache.kafka.common.serialization.StringSerializer");
props.put("partitioner.class",
"org.apache.kafka.clients.producer.internals.DefaultPartitioner");
Thread.currentThread().setContextClassLoader(null);
Producer<String, String> producer = new KafkaProducer <String, String>(props);
for(int i = 0; i < 10; i++){
producer.send(new ProducerRecord<String, String>(topicName,
Integer.toString(i), Integer.toString(i) + i));
}
producer.close();
}catch(Exception e){
e.printStackTrace();
}
Client code snippet:
<!DOCTYPE html>
<html>
<head>My Page</head>
<script src="stomp.js"></script>
<script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>
<script type="text/javascript">
console.log('Starting: ');
var socket = new SockJS('ws://localhost:9092');
client = Stomp.over(socket);
client.connect( "", "",
function() {
console.log('Connected: ');
client.subscribe("/topic/test",
function( message ) {
alert( message );
}
);
}
);
</script>
</html>
From client side, while we are trying to connect via ws, only the Starting: console is getting printed and Connected: is not getting rpinted since the
websocket connection to the kafka server is not getting succeeded.
Since STOMP is not directly supported for Kafka, we tried to sue SockJS.
Can anyone please help us out to achieve this functionality.
New to JavaScript and Node.js
I have a setup where I have a raspberry pi running Node.js. The raspberry pi is connected to some embedded device through a USB to UART connection with the USB plugged into the raspberry pi. I can send and receive data at this base level just fine. The pi is connected to a router and I access it through it's IP and a browser.
I want to host a simple webpage that has a title, some text, and a button. When I click the button I want my client machine to contact the node.js server and make the pi send a message(already have a message format I am required to use) over the serial port to the embedded device. I want to wait/or not(depends on suggestions) for data to be sent back and then use that data to repopulate the text on the webpage.
What I have is close to this but not complete.
I run a 'server' on node.js off the pi. It uses express and a static page. The static page has a client side JavaScript file that executes a AJAX request when the button is clicked. On the node.js side I have express able to see the AJAX request. I then construct and send my message over serial port to the embedded device using serialport. At this point, on the Node.js side I can send back a string of text/etc. that can be displayed by the webpage but don't know how to somehow wait or other wise receive the data and send it to the webpage for displaying.
Client .html:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Request Sensor Data</title>
<style type="text/css" media="screen"></style>
</head>
<body>
<p>Sensor Data</p>
<p><TEXTAREA id="myTxtArea" NAME="sensorDataTxtBox" ROWS=3 COLS=30 ></TEXTAREA></br>
<button type="button" name="sensorButton" id="mySensorButton" onClick="getSensorData()" >Get Sensor Data</button></p>
<script src="clientCode.js"></script>
</body>
</html>
Client .js:
function getSensorData()
{
console.log('getSensorData() button pushed.');
var xhr = new XMLHttpRequest();
xhr.open('GET', 'sensorGET');
xhr.send(null);
xhr.onreadystatechange = function () {
var DONE = 4; // readyState 4 means the request is done.
var OK = 200; // status 200 is a successful return.
if (xhr.readyState === DONE)
{
if (xhr.status === OK)
{
//insert DOM grabs to set text in html textbox.
console.log(xhr.responseText); // 'This is the returned text.'
var textAreaDOM = document.getElementById('myTxtArea');
textAreaDOM.value = textAreaDOM.value + 'inserted sensor data here\n';
}
else
{
console.log('Error: ' + xhr.status); // An error occurred during the request.
}
}
};
}
node.js .js:
var express = require('express'),
app = express();
app.use('/', express.static(__dirname + '/'));
app.get('/sensorGET', function (req, res) {
var sensorData = getSensorData();
res.send('sensorData');
})
var serialport = require('serialport'),
portname = '/dev/ttyUSB0';
var myPort = new serialport(portname, {
baudRate: 115200,
dataBits: 8,
parity: 'none',
stopBits: 1,
flowControl: false,
parser: serialport.parsers.byteLength(1)
});
myPort.on('open', showPortOpen);
myPort.on('data', recSerialData);
myPort.on('close', showPortClosed);
myPort.on('error', showError);
myPort.on('disconnect', showDisconnect);
function showDisconnect() {
console.log('Someone disconnected');
}
function showPortOpen()
{
console.log('port open. Data rate: ' + myPort.options.baudRate);
}
function recSerialData(data)
{
parseMessage(data);//This function is not shown but parses a message that is sent on the wire
}
function showPortClosed()
{
console.log('port closed.');
}
function showError(error)
{
console.log('Serial port error: ' + error);
}
function getSensorData()
{
myPort.write(Assume correct message is sent here);
//Can return some set text here and it will be written to the webpage.
//example: return "Temp data was asked for...";
//is there a way to wait here for the next message that comes in?
}
Probably the simplest thing will actually be to use something like socket.io and just send the data to the browser with that after every parseMessage. Because for starters if you try to make http wait for all serial data it will likely timeout, and the way things work its just easier to send every time you get a new data event from the serial port.
we have a problem regarding Websocket Communication with a Windows-Client.
As minimal setup we use the python3 autobahn websocket ping-pong example.
The server is from (taken from https://github.com/crossbario/autobahn-python/blob/master/examples/asyncio/websocket/echo/server.py). The only modification is that the server sends a message to the client when the connection is opened.
The client is also taken form the autobahn pingpong example but modified in two ways. It accepts connections from a remote server and it does not send a message to the server but it expects one.
This does work well on all browsers on my Linux Machine, but it does not work from a Windows-Client. But if I send a message from the client as soon as the connection is opened, then the client is also able to receive the messages.
Here is the pyhton3 server:
from autobahn.asyncio.websocket import WebSocketServerProtocol, \
WebSocketServerFactory
class MyServerProtocol(WebSocketServerProtocol):
def onConnect(self, req.uest):
print("Client connecting: {0}".format(request.peer))
def onOpen(self):
print("WebSocket connection open.")
self.sendMessage('server hello'.encode('utf8'))
def onMessage(self, payload, isBinary):
if isBinary:
print("Binary message received: {0} bytes".format(len(payload)))
else:
print("Text message received: {0}".format(payload.decode('utf8')))
# echo back message verbatim
self.sendMessage(payload, isBinary)
def onClose(self, wasClean, code, reason):
print("WebSocket connection closed: {0}".format(reason))
if __name__ == '__main__':
import asyncio
factory = WebSocketServerFactory(u"ws://0.0.0.0:9000", debug=False)
factory.protocol = MyServerProtocol
loop = asyncio.get_event_loop()
coro = loop.create_server(factory, '0.0.0.0', 9000)
server = loop.run_until_complete(coro)
try:
loop.run_forever()
except KeyboardInterrupt:
pass
finally:
server.close()
loop.close()
Here is the Websocket Client:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
var socket = null;
var isopen = false;
window.onload = function() {
socket = new WebSocket("ws://" + location.hostname + ":9000");
socket.onopen = function() {
console.log("Connected!");
isopen = true;
//if I do this, then it works
//socket.send('hello from client'.encode('utf-8'))
}
socket.onmessage = function(e) {
console.log("Text message received: " + e.data);
}
socket.onclose = function(e) {
console.log("Connection closed.");
socket = null;
isopen = false;
}
};
</script>
</head>
<body>
</body>
</html>
Has anybody an idea what I am missing? I want to open a connection from server to client without sending a message from the client first.
I'm using Ratchet WebSockets and Autobahn.js for two-way client-server communication. I've installed everything, opened the ports, it's been weeks (yes, literally weeks) and it still doesn't work. I think I've narrowed it down to Autobahn's subscribe method not working correctly.
What I'm using is a slight modification of the example code found here:
http://socketo.me/docs/push
Here is my client code:
<script>
window.define = function(factory) {
try{ delete window.define; } catch(e){ window.define = void 0; } // IE
window.when = factory();
};
window.define.amd = {};
</script>
<script src="/apps/scripts/when.js"></script>
<script src="http://autobahn.s3.amazonaws.com/js/autobahn.min.js"></script>
<script>
var conn = new ab.Session(
'ws://light-speed-games.com:8080' // The host (our Ratchet WebSocket server) to connect to
, function() { // Once the connection has been established
console.log('Connection established.');
conn.subscribe('kittensCategory', function(topic, data) {
// This is where you would add the new article to the DOM (beyond the scope of this tutorial)
console.log('New article published to category "' + topic + '" : ' + data.title);
});
}
, function() { // When the connection is closed
console.warn('WebSocket connection closed');
}
, { // Additional parameters, we're ignoring the WAMP sub-protocol for older browsers
'skipSubprotocolCheck': true
}
);
</script>
I believe the problem lies here:
function() { // Once the connection has been established
console.log('Connection established.');
conn.subscribe('kittensCategory', function(topic, data) {
// This is where you would add the new article to the DOM (beyond the scope of this tutorial)
console.log('New article published to category "' + topic + '" : ' + data.title);
});
}
The line console.log('Connection established.'); does its job - it logs its message in the console. However, the conn.subscribe method does nothing. It doesn't matter if I change kittensCategory to any other string, it still does nothing. But kittensCategory is the only thing that makes sense here (see Ratchet's example code through the link above).
Any ideas?
EDIT:
This is the output of ab.debug:
WAMP Connect autobahn.min.js:69
ws://light-speed-games.com:8080 autobahn.min.js:69
wamp autobahn.min.js:69
WS Receive autobahn.min.js:64
ws://light-speed-games.com:8080 [null] autobahn.min.js:64
1 autobahn.min.js:64
[0,"52cbe9d97fda2",1,"Ratchet\/0.3"] autobahn.min.js:64
WAMP Welcome autobahn.min.js:67
ws://light-speed-games.com:8080 [52cbe9d97fda2] autobahn.min.js:67
1 autobahn.min.js:67
Ratchet/0.3 autobahn.min.js:67
Connection established. client.php:15
WAMP Subscribe autobahn.min.js:74
ws://light-speed-games.com:8080 [52cbe9d97fda2] autobahn.min.js:74
kittensCategory autobahn.min.js:74
function (topic, data) {
// This is where you would add the new article to the DOM (beyond the scope of this tutorial)
console.log('New article published to category "' + topic + '" : ' + data.title);
} autobahn.min.js:74
WS Send autobahn.min.js:72
ws://light-speed-games.com:8080 [52cbe9d97fda2] autobahn.min.js:72
1 autobahn.min.js:72
[5,"kittensCategory"]
trying to make a simple text chat socket server. I am very new to coding servers. I have this working code but the problem is that the WebSocket() dies silently on me:
the output in the javascript console is
open
closed
There is very little resources to help me understand this behaviour. Why does my python server kill the connection once the header is sent? Am i sending the response in the correct way? Any help at all would be amazing.
Python code:
import socketserver
import re
from base64 import b64encode
from hashlib import sha1
inited = 0
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
global inited
if(inited==0):
print(self)
text = self.request.recv(1024).strip()
self.upgradeConnection(text)
self.request.send("a sweet message from the server!".encode("utf-8"));
inited = 1
else:
self.request.sendall("second response!".encode("utf-8"));
def upgradeConnection(self,text):
#print("Client wants to upgrade:")
#print(text);
websocket_answer = (
'HTTP/1.1 101 Switching Protocols',
'Upgrade: websocket',
'Connection: Upgrade',
'Sec-WebSocket-Accept: {key}\r\n\r\n',
)
GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
#print(re.search(b'Sec-WebSocket-Key:\s+(.*?)[\n\r]+', text))
key = (re.search(b'Sec-WebSocket-Key:\s+(.*?)[\n\r]+', text)
.groups()[0]
.strip())
#print(key.decode("utf-8"))
#print(key.decode("utf-8") + GUID)
#print(sha1((key.decode("utf-8") + GUID).encode("utf-8")))
response_key = b64encode(sha1((key.decode("utf-8") + GUID).encode("utf-8")).digest()).decode("utf-8")
#print(response_key)
response = '\r\n'.join(websocket_answer).format(key=response_key)
self.request.send(response.encode("utf-8"));
HOST, PORT = "localhost", 9999
server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
Webpage code:
url = "ws://127.0.0.1:9999/";
var sk = new WebSocket(url);
sk.onopen = function(e){
console.log("open");
sk.send("the client is here!!");
}
sk.onmessage = function(e){
console.log("message");
console.log(e.data);
}
sk.onerror = function(e){
console.log("error");
}
sk.onclose = function(e){
console.log("closed");
}