How would I have a web based application commincate with a python server with sockets [duplicate] - python

I have a vb.net application that opens a socket and listens on it.
I need to communicate via this socket to that application using a javascript running on a browser. That is i need to send some data on this socket so that the app which is listening on this socket can take that data, do some stuff using some remote calls and get some more data and put it back on the socket that my javascript needs to read and print it in the browser.
Ive tried, socket.io, websockify but none have proved to be useful.
Hence the question, is what i am trying even possible? Is there a way that a javascript running in a browser can connect to a tcp socket and send some data and listen on it for some more data response on the socket and print it to the browser.
If this is possible can some one point me in the right direction as to which would help me establish the goal.

As for your problem, currently you will have to depend on XHR or websockets for this.
Currently no popular browser has implemented any such raw sockets api for javascript that lets you create and access raw sockets, but a draft for the implementation of raw sockets api in JavaScript is under-way. Have a look at these links:
http://www.w3.org/TR/raw-sockets/
https://developer.mozilla.org/en-US/docs/Web/API/TCPSocket
Chrome now has support for raw TCP and UDP sockets in its ‘experimental’ APIs. These features are only available for chrome apps and, although documented, are hidden for the moment. Having said that, some developers are already creating interesting projects using it, such as this IRC client.
To access this API, you’ll need to enable the experimental flag in your extension’s manifest. Using sockets is pretty straightforward, for example:
chrome.experimental.socket.create('tcp', '127.0.0.1', 8080, function(socketInfo) {
chrome.experimental.socket.connect(socketInfo.socketId, function (result) {
chrome.experimental.socket.write(socketInfo.socketId, "Hello, world!");
});
});

This will be possible via the navigator interface as shown below:
navigator.tcpPermission.requestPermission({remoteAddress:"127.0.0.1", remotePort:6789}).then(
() => {
// Permission was granted
// Create a new TCP client socket and connect to remote host
var mySocket = new TCPSocket("127.0.0.1", 6789);
// Send data to server
mySocket.writeable.write("Hello World").then(
() => {
// Data sent sucessfully, wait for response
console.log("Data has been sent to server");
mySocket.readable.getReader().read().then(
({ value, done }) => {
if (!done) {
// Response received, log it:
console.log("Data received from server:" + value);
}
// Close the TCP connection
mySocket.close();
}
);
},
e => console.error("Sending error: ", e)
);
}
);
More details are outlined in the w3.org tcp-udp-sockets documentation.
http://raw-sockets.sysapps.org/#interface-tcpsocket
https://www.w3.org/TR/tcp-udp-sockets/
Another alternative is to use Chrome Sockets
Creating connections
chrome.sockets.tcp.create({}, function(createInfo) {
chrome.sockets.tcp.connect(createInfo.socketId,
IP, PORT, onConnectedCallback);
});
Sending data
chrome.sockets.tcp.send(socketId, arrayBuffer, onSentCallback);
Receiving data
chrome.sockets.tcp.onReceive.addListener(function(info) {
if (info.socketId != socketId)
return;
// info.data is an arrayBuffer.
});
You can use also attempt to use HTML5 Web Sockets (Although this is not direct TCP communication):
var connection = new WebSocket('ws://IPAddress:Port');
connection.onopen = function () {
connection.send('Ping'); // Send the message 'Ping' to the server
};
http://www.html5rocks.com/en/tutorials/websockets/basics/
Your server must also be listening with a WebSocket server such as pywebsocket, alternatively you can write your own as outlined at Mozilla

ws2s project is aimed at bring socket to browser-side js. It is a websocket server which transform websocket to socket.
ws2s schematic diagram
code sample:
var socket = new WS2S("wss://ws2s.feling.io/").newSocket()
socket.onReady = () => {
socket.connect("feling.io", 80)
socket.send("GET / HTTP/1.1\r\nHost: feling.io\r\nConnection: close\r\n\r\n")
}
socket.onRecv = (data) => {
console.log('onRecv', data)
}

See jsocket. Haven't used it myself. Been more than 3 years since last update (as of 26/6/2014).
* Uses flash :(
From the documentation:
<script type='text/javascript'>
// Host we are connecting to
var host = 'localhost';
// Port we are connecting on
var port = 3000;
var socket = new jSocket();
// When the socket is added the to document
socket.onReady = function(){
socket.connect(host, port);
}
// Connection attempt finished
socket.onConnect = function(success, msg){
if(success){
// Send something to the socket
socket.write('Hello world');
}else{
alert('Connection to the server could not be estabilished: ' + msg);
}
}
socket.onData = function(data){
alert('Received from socket: '+data);
}
// Setup our socket in the div with the id="socket"
socket.setup('mySocket');
</script>

In order to achieve what you want, you would have to write two applications (in either Java or Python, for example):
Bridge app that sits on the client's machine and can deal with both TCP/IP sockets and WebSockets. It will interact with the TCP/IP socket in question.
Server-side app (such as a JSP/Servlet WAR) that can talk WebSockets. It includes at least one HTML page (including server-side processing code if need be) to be accessed by a browser.
It should work like this
The Bridge will open a WS connection to the web app (because a server can't connect to a client).
The Web app will ask the client to identify itself
The bridge client sends some ID information to the server, which stores it in order to identify the bridge.
The browser-viewable page connects to the WS server using JS.
Repeat step 3, but for the JS-based page
The JS-based page sends a command to the server, including to which bridge it must go.
The server forwards the command to the bridge.
The bridge opens a TCP/IP socket and interacts with it (sends a message, gets a response).
The Bridge sends a response to the server through the WS
The WS forwards the response to the browser-viewable page
The JS processes the response and reacts accordingly
Repeat until either client disconnects/unloads
Note 1: The above steps are a vast simplification and do not include information about error handling and keepAlive requests, in the event that either client disconnects prematurely or the server needs to inform clients that it is shutting down/restarting.
Note 2: Depending on your needs, it might be possible to merge these components into one if the TCP/IP socket server in question (to which the bridge talks) is on the same machine as the server app.

The solution you are really looking for is web sockets. However, the chromium project has developed some new technologies that are direct TCP connections TCP chromium

Related

HTTP Server using Python Socket and multiple requests from one client [duplicate]

If a browser opens a connection to a remote server, is it possible to access that same connection via Javascript?
I have a small Ethernet module on my network that I program sort of like this (pseudocode):
private var socket
while(true) {
if(socket is disconnected) {
open socket
listen on socket (port 80)
}
if(connection interrupt) {
connect socket
}
if(data receive interrupt) {
serve
}
if(disconnection interrupt) {
disconnect socket
}
}
The point is that it listens on one socket for HTTP requests and serves them.
In my web browser, I can connect to the device, making an HTTP GET request for some HTML/JS that I've written, and it works. A connection is opened on the socket and the files come back as HTTP responses.
Now I want to click a button on the webpage and have the browser send an HTTP POST request over that same connection. In my Javascript, I have (edited and formatted for clarity):
// This function sends an HTTP request
function http(type, url, data, callbacks) {
// make a new HTTP request
var request = new XMLHttpRequest();
// open a connection to the URL
request.open(type, url + (data ? "?" + data : ""));
// add headers
if(type == "POST")
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// register callbacks for the request
Object.keys(callbacks).forEach(function(callback) {
request[callback] = function() {
callbacks[callback](request.responseText);
};
});
// send and return the request
request.send();
return request;
}
// Here is where I call the function
http("POST", // use POST method
"http://192.168.1.99", // IP address of the network device
dataToSend, // the data that needs to be sent
{ // callbacks
onloadend: function(data) {
console.log("success. got: " + data); // print 'success' when the request is done
},
onerror: function(data) {
console.log("There was an error."); // print 'error' when it fails
console.log(data);
}
}
);
The issue here is that this opens a new connection to the device, but I want to use the same socket that the browser is already connected to. Is this possible, and if so, how?
There is no application control inside the browser to decide if a new connection is used for the next request or if an existing connection is used. In fact, it is perfectly normal that the browser will use multiple connections in parallel to the same server and your server has to be able to deal with this.
Since your server architecture seems to be only able to deal with one connection at a time you either would need to change the architecture to handle multiple parallel connections or to make sure that you only need to handle a single connection at a time. The latter could be achieved by not supporting HTTP keep-alive, i.e. by closing the connection immediately after each response. This way a new request will result in a new connection (which is not what you wanted according to your question) but your server will also be able to handle this new connection (which is what you likely ultimately need) since the previous one was closed.

How can I make my client and server IPv6 compatible? (Flutter, Python, Nginx)

I have a mobile app that sends location information to database. The server (Tavu.io) is Ubuntu based and uses Nginx. The problem is that when I try to connect to the server using IPv6 address, the data is not transferred. The application should work in IPv6 network only. UDP protocol should be used.
In the nginx.conf, there are path to files included that contain:
listen 80 default_server;
listen [::]:80 default_server;
netstat -pnltu shows that "tcp" and "tcp6" have LISTEN. But, there is only "udp", and no "udp6" which I assume it should be. There is no LISTEN on "udp".
My Python socket is like this:
self.connection = db.connect_to_database()
self.status = True
self.udp = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)
self.udp.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
self.udp.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
self.udp.bind(('', 50943))
And the mobile client (Dart/Flutter):
static String serverIP = '[ipv4 address hardcoded]';
static Future<RawDatagramSocket> rDgS =
RawDatagramSocket.bind(InternetAddress.anyIPv4, 50943);
rDgS.then(
(RawDatagramSocket udpSocket) {
udpSocket.writeEventsEnabled = true;
List<int> data = utf8.encode(message);
udpSocket.send(data, InternetAddress(serverIP), 50943);
},
);
That above code works at that state as intended, but when is use hardcoded IPv6 address and change to .anyIPv6, the sent data is not reaching the server. No error is shown on the VSCode console though. The reason the IP addresses are hard coded because I don't have the hostname for the server and giving server name to nginx.conf was not working. Is there a workaround to this issue to have client to connect to server while in IPv6-only network?
I have changed the settings on nginx and attempted multiple times this application on IPv6-only network but the data (location and username) are not sent to database.

Is there a way to write websocket code in a standard way?

It seems that every single language and all of its web socket libraries uses its own slightly different quirky method to write its web socket code, slightly different code, slightly different language, some longer, some shorter, some simpler and some harder, but there is no consensus, is there a way to make my python and node.js web socket code server the same, and make them equal to browser's inbuilt socket, or must I learn each different code?
Examples:
1: Python with asyncio
import websockets
# create handler for each connection
async def handler(websocket, path):
data = await websocket.recv()
reply = f"Data recieved as: {data}!"
await websocket.send(reply)
start_server = websockets.serve(handler, "localhost", 8000)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
Example 2: Node.js with ws
import { WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
console.log('received: %s', message);
});
ws.send('something');
});
enter code here
Client side example:
const socket = new WebSocket('ws://localhost:8000');
socket.addEventListener('open', function (event) {
socket.send('Connection Established');
});
socket.addEventListener('message', function (event) {
console.log(event.data);
});
const contactServer = () => {
socket.send("Initialize");
The issue is that they are all so different, is there a way to solve this problem
I have realized that those modules don't add "much" on their own and in fact just use the formatting of the language it self, albeit the examples are a little advanced
The general formula is
import module or library (mostly language specific, some differences depending on module)
start http server (language specific)
mount module on top of http server (mostly language specific, some differences depending on module)
send and receive information, usually in the following format, I will use socket.io as an example because its what I know but most use a similar format with change being mostly language specific
//to send
connection.send("recieve_this", information_being_sent)
//to receive
socket.on("recieve_this", function(information_being_sent){
//receives (information_being_sent) and starts a function that you can do work on
})
Here is an example of a full server running in javascript with socket.io
var http = require('http'); //important for hosting a server on http
const { Server } = require("socket.io");//requires the imported socket module
const server = http.createServer(function(recieve, send){
}).listen(8000) //starts http server on port 8000 (can be any port you like)
const connection = new Server(server); //creates a variable called connection and mounts socket.io's Server to http's server
//to send
connection.send("recieve_this", information_being_sent)
//to receive
socket.on("recieve_this", function(information_being_sent){
//receives (information_being_sent) and starts a function that you can do work on
})
This is all server code, you will need to sent client a script as well, read documentation.

C# to Python messaging

I want to send and receive very simple data (doesn't matter what form) from/to C# to/from a python program on a raspberry pi using ZeroMQ. For my server side I am using the following C# code:
using System;
using System.Threading;
using NetMQ;
using NetMQ.Sockets;
namespace NetMQServer
{
class Program
{
static void Main(string[] args)
{
using (var server = new ResponseSocket())
{
server.Bind("tcp://*:5555");
while (true)
{
Console.ReadKey();
var message = server.ReceiveFrameString();
Console.WriteLine("Received {0}", message);
// processing the request
Console.WriteLine("Sending World");
server.SendFrame("World");
}
}
}
}
}
and on the client side (python) I am using the following code:
import zmq
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect("tcp://192.168.1.14:5555")
for i in range(0, 10):
print("Sending Hello")
socket.send_string("Hello")
msg = socket.recv_string()
print("recieved ", msg)
print("")
both programs run but it does not print anything in the console as if they are not connected. I have tried it with both client and server in the same language with the exact same codes above and it works.
I run your code on a local machine and cannot reproduce your issue - an interaction between client and server works fine.
Just one remark, this code:
Console.ReadKey();
should be removed from the server-side.
I would recommend:
make sure that all works on a local machine
check that port 5555 is available (not blocked by a firewall, etc) from the client-side. To test it can be used telnet utility:
telnet 192.168.1.14 5555

How to create a node js API for which users can subscribe to listen to events?

I am trying to create and node.js api to which users can subscribe to get event notifications?
I created the below API and was able to call the API using python ,however its not clear to me how can folks subscribe to it?
How can folks subscribe to this API to get notification of New root build released?what do I need to change?
node.js API
app.get("/api/root_event_notification", (req, res, next) => {
console.log(req.query.params)
var events = require('events');
var eventEmitter = new events.EventEmitter();
//Create an event handler:
var myEventHandler = function () {
console.log('new_root_announced!');
res.status(200).json({
message: "New root build released!",
posts: req.query.params
});
}
import requests
python call
input_json = {'BATS':'678910','root_version':'12A12'}
url = 'http://localhost:3000/api/root_event_notification?params=%s'%input_json
response = requests.get(url)
print response.text
OUTPUT:-
{"message":"New root build released!","posts":"{'root_version': '12A12', 'BATS': '678910'}"}
You can't just postpone sending an http response for an arbitrary amount of time. Both client and server (and sometimes the hosting provider's infrastructure) will timeout the http request after some number of minutes. There are various tricks to try to keep the http connection alive, but all have limitations.
Using web technologies, the usual options for get clients getting updated server data:
http polling (client regularly polls the server). There's also a long polling adaptation version of this that attempts to improve efficiency a bit.
Websocket. Clients makes a websocket connection to the server which is a lasting, persistent connection. Then either client or server can send data/events of this connection at any time, allowing the server to efficiently send notifications to the client at any time.
Server Sent Events (SSE). This is a newer http technology that allows one-way notification from server to client using some modified http technology.
Since a server cannot typically connect directly to a client due to firewall and public IP address issues, the usual mechanism for a server to notify a client is to use either a persistent webSocket connection from client to server over which either side can then send webSocket packets or use the newer SSE (server sent events) which allows some server events to be sent to a client over a long lasting connection.
The client can also "poll" the server repeatedly, but this is not really an event notification system (and not particularly efficient or timely) as much as it is some state that the client can check.

Categories

Resources