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.
Related
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>
I am trying to implement a server client project which needs the server to send data to the client every 5 minutes with the client only asking in the beginning of connection. Server-sent events seem to be the go-to solution.
I have tried to use the functions given in the Javalin Documents. I am able to receive a response with a simple get from the server. But I couldn't establish a sse connection. The code enters the lambda function in the server but the client does not receive anything. I am not sure if the client or the server, or even both have a problem.
The only output we get from the codes below is "connected" on the server side. Thank you in advance.
Code for the server
import io.javalin.Javalin;
public class SimpleTwitter {
public static void main(String[] args) {
Javalin app = Javalin.create().start(7000);
app.sse("/sse", client ->{
System.out.println("connected");
client.sendEvent("message","Hello, SSE");
client.onClose(() -> System.out.println("Client disconnected"));
});
app.get("/", ctx -> ctx.result("Hello World"));
}
}
Code for the client
<!DOCTYPE html>
<html>
<body>
<h1>Getting server updates</h1>
<div id="result"></div>
<script>
if(typeof(EventSource) !== "undefined") {
var source = new EventSource("http://localhost:7000/sse");
source.onmessage = function(event) {
document.getElementById("result").innerHTML += event.data + "<br>";
};
} else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
}
</script>
</body>
</html>
Turns out the problem was not the code. By looking at the developer tools on chrome, we saw the following:
"Access to resource at 'http://localhost:7000/sse' from origin 'null'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin'
header is present on the requested resource."
When we installed a chrome extention called "Allow-Control-Allow-Origin: *", we were able to see the output.
Also, here are the updated better working codes:
> <<!DOCTYPE html> <html> <body>
>
> <h1>Tweets</h1>
>
> <script> new
> EventSource('http://localhost:7000/sse').addEventListener( "hi", msg
> =>{ document.write(msg.data); }); </script>
>
> </body> </html>
...
public static void main(String[] args) throws InterruptedException {
Queue<SseClient> clients = new ConcurrentLinkedQueue<>();
Javalin app = Javalin.create().start(7000);
app.sse("/sse", client -> {
clients.add(client);
client.onClose(() -> clients.remove(client));
});
while (true) {
for (SseClient client : clients) {
client.sendEvent("hi", "hello world");
}
TimeUnit.SECONDS.sleep(1);
}
}
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.
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");
}