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");
}
Related
I'm trying to send the url of the currently active tab to a python script. My extension already starts running the script and tries to send the url. However I have so far been unsuccessfull in receiving the url with the running script.
popup.js:
dlvideo.addEventListener("click", async () => {
chrome.tabs.query({active: true, lastFocusedWindow: true}, tabs => {
// Get current url
url = tabs[0].url;
// Connect to python script
port = chrome.runtime.connectNative('com.ytdlp.batdlvideo');
port.onDisconnect.addListener(function() {
console.log("Disconnected");
});
port.onMessage.addListener(function(msg) {
console.log("Received" + msg);
});
// Send url to script
port.postMessage({ text: url });
});
});
dlvideo.py (the code seems to get stuck here at the start of the while-loop):
import sys
if sys.platform == "win32":
import os, msvcrt
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
url = None
while True:
# The loop seems to get stuck here:
text_length_bytes = sys.stdin.read(4)
if len(text_length_bytes) == 0:
print("test.py: sys.exit0")
sys.exit(0)
text_length = struct.unpack('i', text_length_bytes)[0]
text = sys.stdin.read(text_length).decode('utf-8')
if text.startswith('http'):
url = text
print(str(url))
break
else:
print(text)
Other files are probably not relevant, but I'll put them here just in case:
yt_dlp.bat:
#echo off
start cmd /k python "%~dp0/dlvideo.py" %*
manifestAPP.json:
{
"name": "com.ytdlp.batdlvideo",
"description": "Youtube-dlp",
"path": "C:\\Users\\.....\\native-apps\\dlvideo\\yt_dlp.bat",
"type": "stdio",
"allowed_origins": [
"chrome-extension://-extensionid-/"
]
}
Can someone help?
Ok, I think in my case the problem was that only one message is sent to the host and the host is not yet ready by the time it is sent?
Well, this at least is the code that worked for me:
popup.js and manifestAPP.json can stay the same.
dlvideo.py:
import struct
import json
import sys
import os
# Changes the stdio-mode
if sys.platform == "win32":
import os, msvcrt
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
# Read native message from chrome window
text_message_length = sys.stdin.buffer.read(4)
text_length = struct.unpack("i", text_message_length)[0]
text_decoded = sys.stdin.buffer.read(text_length).decode("utf-8")
text_asstr = json.loads(text_decoded)
# Get URL
url = text_asstr['text']
yt_dlp.bat:
#echo off
python dlvideo.py %*
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>
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.
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.
Here is what I am working with:
webserver.py:
import sys
from twisted.internet import reactor
from twisted.python import log
from autobahn.websocket import WebSocketServerFactory, \
WebSocketServerProtocol, \
listenWS
class EchoServerProtocol(WebSocketServerProtocol):
def onMessage(self, msg, binary):
print "sending echo:", msg
self.sendMessage(msg, binary)
if __name__ == '__main__':
log.startLogging(sys.stdout)
factory = WebSocketServerFactory("ws://localhost:9000", debug = False)
factory.protocol = EchoServerProtocol
listenWS(factory)
reactor.run()
background.js:
function updateCookies(info) {
send();
console.log(info.cookie.domain);
}
function send() {
msg = "TEST";
sock.send(msg);
};
var sock = null;
sock = new WebSocket("ws://localhost:9000");
console.log("Websocket created...");
sock.onopen = function() {
console.log("connected to server");
sock.send("CONNECTED TO YOU");
}
sock.onclose = function(e) {
console.log("connection closed (" + e.code + ")");
}
sock.onmessage = function(e) {
console.log("message received: " + e.data);
}
chrome.cookies.onChanged.addListener(updateCookies);
Now, upon running webserver.py and running background.js, nothing happens. The client see's no echo and the server doesn't report any connections or messages. However, if I reload background.js, all the sudden the previous message of "CONNECTED TO YOU" is shown by the server. Reloading again produces the same effect, showing the delayed "CONNECTED TO YOU" message. I've tried running sock.close() after sending the message, but that still produces nothing. I'm really confused at what is causing this random delay. Leaving the server running for 10 - 15 minutes also produces nothing, I must manually refresh the page before I see any messages. Any idea what might be causing this?