I saw that this problem is quite common, but I couldn't figure it out how to solve it in my case.
I'm creating a server in Python like this:
clients = []
server = None
class SimpleWSServer(WebSocket):
def handleConnected(self):
clients.append(self)
def handleClose(self):
clients.remove(self)
def run_server():
global server
server = SimpleWebSocketServer('', 9000, SimpleWSServer,
selectInterval=(1000.0 / 15) / 1000)
server.serveforever()
t=threading.Thread(target=run_server)
t.start()
if( ...)
for client in clients:
msg = json.dumps({'x': cX, 'y': cY})
client.sendMessage(unicode(msg))
and I'm open a WebSocket using three.js in this way:
var ws = new WebSocket('ws://192.168.0.15:9000/');
ws.onopen = function() {
console.log('onopen');
};
ws.onmessage = function (event) {
var m = JSON.parse(event.data);
history.push({ x: m.x * 2 - 1, y: -m.y * 2 + 1});
window.alert("X: "+x + " Y "+ y)
// ... rest of the function.
};
The localhost server is created using node.js and I don't have any errors in the log, meanwhile in Google Chrome I have the error: " threejs_prova.js:3 WebSocket connection to 'ws://192.168.0.15:9000/' failed: Connection closed before receiving a handshake response"
Error in Firefox is:
Firefox can't connect to server ws://192.168.0.15:9000/
In my case changing
var ws = new WebSocket('ws://192.168.0.15:9000/');
with
var ws = new WebSocket('ws://localhost:9000/');
solved the problem
Related
I'm working on a project, where I have to connect Python and C# in a rather flexible way, with information being send from one to the other frequently. Most of the time, the data goes back and forth (A works with data, sends result to B, B works with result, answers A) but not necessary always.
Named pipes seemed like the way to go but I'm struggling with keeping it all synchronous.
Currently I'm just starting a server on one of them and let it wait for a client connection, while the other creates a server as well, and connects as a client when the server is ready.
It's a lot of creating servers and clients and trying to not break it, which happens as soon as a client tries to connect to an not existing server..
I'd like to do it with a pipe that runs in a separate thread, but couldn't find a way to keep it alive, it simply closes, when the client is done reading.
Are named pipes just too simplistic for such a task, or is there a way to make this work robustly?
Update:
For reference, how my code looks like (reduced to the minimum here):
First the NamedPipe Server and Client in C#
public static void SendDataToPython(string payload)
{
using (var server = new NamedPipeServerStream("Test"))
{
server.WaitForConnection();
using (var stream = new MemoryStream())
using (var writer = new BinaryWriter(stream))
{
writer.Write(payload);
server.Write(stream.ToArray(), 0, stream.ToArray().Length);
}
server.Disconnect();
}
}
public static string WaitForMessage()
{
string message = "";
string servername = ".";
string pipeName = "CSServer";
using (var pipeClient = new NamedPipeClientStream(servername, pipeName, PipeDirection.In))
{
pipeClient.Connect();
And in Python:
class PipeServer():
def __init__(self, pipeName):
self.pipe = win32pipe.CreateNamedPipe(
r'\\.\pipe\\' + pipeName,
win32pipe.PIPE_ACCESS_DUPLEX,
win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_READMODE_MESSAGE | win32pipe.PIPE_WAIT,
1, 65536, 65536,
0,
None)
def connect(self):
win32pipe.ConnectNamedPipe(self.pipe, None)
def write(self, message):
win32file.WriteFile(self.pipe, message.encode() + b'\n')
def close(self):
win32file.CloseHandle(self.pipe)
using (StreamReader sr = new StreamReader(pipeClient))
{
string temp;
while ((temp = sr.ReadLine()) != null)
{
message += temp;
}
}
}
return message;
}
class PipeClient:
def __init__(self, pipeName):
self.pipeName = pipeName
def receive(self):
file_handle = win32file.CreateFile(
f"\\\\.\\pipe\\{self.pipeName}",
win32file.GENERIC_READ | win32file.GENERIC_WRITE,
0,
None,
win32file.OPEN_EXISTING,
0,
None)
left, data = win32file.ReadFile(file_handle, 4096)
print(data.decode("utf-8")[1:])
Description
So basically i am building an android app in which i am using kotlin and which will behave as server.Whilst on the client side i am using python.I am using sockets for this purpose.I have to communicate using UDP.But i am unable to make connection to my android app.In python script sock.connect(('10.0.2.2', 6000)) i have also tried placing the emulator ip instead of localhost.I just want to send and receive simple messages.
Another Issue: Python script just times out it does not even gets into the loop.
Server.kt
package com.example.soundsource
import android.content.Intent
import android.os.AsyncTask
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import java.io.BufferedInputStream
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.PrintWriter
import java.lang.Exception
import java.lang.ref.WeakReference
import java.net.ServerSocket
import java.net.Socket
class MainActivity : AppCompatActivity() {
private lateinit var textView:TextView
private var message = " "
private lateinit var client:Socket
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val sendButton:Button = findViewById(R.id.send_button)
val showLocation = findViewById(R.id.show_location) as? Button
showLocation?.setOnClickListener {
val intent = Intent(this,SoundLocation::class.java)
startActivity(intent)
}
textView = findViewById(R.id.text_view)
sendButton.setOnClickListener{
t.start()
}
}
private val t = Thread(Runnable {
val port = 5000
val server = ServerSocket(port)
this.message = "Message from client"
this#MainActivity.runOnUiThread {
this.textView.text = server.localPort.toString()
}
val i = InputStreamReader(this.client.getInputStream())
val b = BufferedReader(i)
while (true){
this.client = server.accept()
message += " "+ this.client.localAddress.toString()+b.readLine()
this#MainActivity.runOnUiThread{
this.textView.text = server.localSocketAddress.toString()
}
t2.start()
}
})
private val t2 = Thread(Runnable {
val p = PrintWriter(this.client.getOutputStream())
p.println("sending message back")
runOnUiThread {
this.textView.text = "message sent...."
}
})
}
Client.py
import socket
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('10.0.2.2', 5000))
while True:
print("you are about to.....")
data = sock.recv(1024)
print('you received :', data)
sock.sendall(bytes("hey kotlin....", 'utf-8'))
main()
So, I'm coding a lua mod for Binding of Isaac. I made a lua client (using luasocket), and a python server.
In local, everything works fine, but when I test it using my public ip (I did the port forwarding on my router), the lua client times out at its second reception.
I don't know what causes it, the log says "timeout at CID".
Edit (forgotten to add this) :
What is weird is that for the python server, it's as if he already sent it, because when I add a timeout on the server, it's only the reception of the message "[RCID]\n" that times out.
Here is the network part of the lua mod:
local socket = require("socket")
local connectIP = ""
local currentPort = 21666
local loopTimeout = 10
function Network.SendData(data)
if currentBehaviour == Behaviour.CLIENT then
client:send(data.."\n")
end
end
function Network.StartClient()
if currentBehaviour == Behaviour.IDLE then
client = assert(socket.tcp())
client:connect(connectIP,currentPort)
currentBehaviour = Behaviour.CLIENT
client:settimeout(loopTimeout)
local seed,errs = client:receive()
if errs~="timeout" and errs~=nil then
Network.CloseConnection();
Isaac.DebugString("seederror:"..errs);
elseif errs=="timeout" then
Network.CloseConnection();
Isaac.DebugString("timeout at seed");
elseif errs==nil then
Isaac.DebugString("Seed: : "..seed);
Isaac.ExecuteCommand("seed "..seed)
end
local CID,err = client:receive()
if err~="timeout" and err~=nil then
Network.CloseConnection();
Isaac.DebugString("ciderror:"..err);
elseif err=="timeout" then
Network.CloseConnection();
Isaac.DebugString("timeout at CID");
elseif err==nil then
Isaac.DebugString("CID : "..CID);
ClientID = tonumber(CID)
Network.SendData("[RCID]")
end
end
end
Here is the server :
import socket
import select
from parse import *
IsaacClients = {}
seed = b"98BN MJ4D\n"
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('', 21666))
server.listen(10)
num_clients = 0
server_launched = True
connected_clients = []
while server_launched:
connections_asked, wlist, xlist = select.select([server],
[], [], 0.05)
for connection in connections_asked:
connection_client, info_client = connection.accept()
print(info_client)
connected_clients.append(connection_client)
print("Sending Seed")
connection_client.sendall(seed) # send the seed
print("Seed Sent")
num_clients = num_clients +1
check = ""
counter = 0
while check != "[RCID]\n" and counter<100: # try 100 times to send the ClientID
print("Sending ClientID")
try:
connection_client.settimeout(0.1)
connection_client.sendall((str(num_clients)+"\n").encode())
check = connection_client.recv(7).decode() # try to check if it has received it
connection_client.settimeout(None)
except:
pass
counter=counter+1
if counter == 100:
server_launched = False
print("ClientID Sent")
clients_to_read = []
try:
clients_to_read, wlist, xlist = select.select(connected_clients,
[], [], 0.05)
except select.error:
pass
else:
for client in clients_to_read:
msg_recved = client.recv(1024)
msg_recved = msg_recved.decode()
print("[] {}".format(msg_recved))
if msg_recved.find("[END]")!= -1 :
server_launched = False
msg_recved = msg_recved.split('\n') # split into lines
for line in msg_recved:
data = parse("[ID]{ID}[POS]{x};{y}[ROOM]{RoomIndex}[CHAR]{CharacterName}[REDM]{MaxHeart}[RED]{Hearts}[SOUL]{SoulHearts}", line)
if data != None :
IsaacClients[data['ID']] = data
luaTable = "{" # start the generation of the lua table that will be sent
for player in IsaacClients.values():
luaTable = luaTable + "[" + player['ID'] +"]={ID=" + player['ID'] + ",POS={x=" +player['x']+ ",y=" +player['y']+ "},ROOM=" +player['RoomIndex']+ ",CHAR='" +player['CharacterName']+ "',REDM=" +player['MaxHeart']+ ",RED=" +player['Hearts']+ ",SOUL=" +player['SoulHearts']+ "}"
luaTable = luaTable + "}\n"
print(luaTable)
print("Sending Table")
client.sendall(luaTable.encode())
print("Table Sent")
print("Server closing")
for client in connected_clients:
client.close()
So, finally, there was no issue, the thing was : my router didn't support hairpinning, making weird bugs when trying to use the public ip from the local network. It works fine whith PCs outside of the network.
i am having trouble trying to send data to all clients connected on my python tcp chat server. i know how to get the message/data to send right back to the person who sent it but it just won't send back if i have multiple clients. this is my server so far:
host = '127.0.0.1'
port = 4446
backlog = 5
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind( (host, port) )
s.listen(backlog)
clients = [s]
while 1:
inputReady, outputReady, exceptReady = select.select(clients, [], [])
for x in inputReady:
if x == s:
csock, addr = s.accept()
clients.append(csock)
else:
data = x.recv(size)
if data:
for i in clients: #problem i believe is in here but i
i.send(data) #dont know how to fix it
else:
x.close()
clients.remove(x)
s.close()
i am using node.js for the client side and its very simple so far and i dont think its the problem:
var net = require('net');
var readline = require('readline');
var host = process.argv[2];
var port = process.argv[3];
var username = process.argv[4];
var client = new net.Socket();
client.connect(port, host, function(){
var type = "connect";
var sender = username;
var msg = "has connected";
var s = type + ':' + sender + ':' + msg;
var length = s.length;
client.write(length + " " + s);
});
client.on('data', function(data){
console.log(data.toString('UTF-8'));
});
The problem is that you are sending on all sockets, including the server socket (s). Ignoring other potential problems, you can do a quick fix by doing this:
for i in clients:
if i is not s:
i.send(data)
I need to receive data from device connected via Ethernet (modbus/TCP) and send it to webpage (maybe using web sockets).
I can't find good examples. Now I can connect with driver and print values using ModbusClientProtocol.read_input_registers() but I had to create own factory and protocol class. I am using autobahn, twisted, pymodbus.
I've no familiarity with modbus or pymodbus, so I'm guessing and leaving a lot of blanks for you to fill in.
This is hacked out of something I recently put together to receive snmptraps and redistribute the information to connected websockets.
Hopefully this is enough to get you going:
#!/usr/bin/python
from twisted.internet import protocol, reactor, utils, defer
from twisted.web.server import Site
from twisted.web.static import File
from autobahn.websocket import WebSocketServerFactory, WebSocketServerProtocol
from autobahn.util import newid
from autobahn.resource import WebSocketResource
class ModbusThing(object):
def __init__(self,clientAddress):
self.clientAddress = clientAddress
self.client = None
def start(self):
pass
## Create client connection to modbus server
## Start Looping Call of pollForData with suitable interval
def pollForData(self):
pass
## Call read methods on ModbusClient object, add call backs to process the results
## Add errorBacks to notify of errors
def resultCallback(self,result):
pass
## Process the data from a read request
## Assumes that your websocket clients expect json like {"event":"update","data":[0,1,2]}
message = dict(event="update",data=processedResults)
self.broadcast(json.dumps(message))
def broadcast(self,msg):
"""Override me"""
pass
class TrackingWebSocketProtocol(WebSocketServerProtocol):
def onOpen(self):
self.session_id = newid()
self.factory._addSession(self,self.session_id)
print "Socket Open %s" % (self.peerstr,)
def onMessage(self,payload,isBinary):
print "Message received from %s\n\t: %r" % (self.peerstr,payload)
def onClose(self,wasClean,code,reason):
self.factory._removeSession(self)
print "Socket Closed %s" % (self.peerstr,)
class TrackingWebSocketFactory(WebSocketServerFactory):
def __init__(self,*args,**kwargs):
WebSocketServerFactory.__init__(self,*args,**kwargs)
self.proto2session = {}
self.session2proto = {}
def _addSession(self,proto,session_id):
if not self.proto2session.has_key(proto):
self.proto2session[proto] = session_id
else:
raise Exception("logic error - dublicate _addSession for protoToSessions")
if not self.session2proto.has_key(session_id):
self.session2proto[session_id] = proto
else:
raise Exception("logic error - dublicate _addSession for sessionsToProto")
def _removeSession(self,proto):
if proto in self.proto2session:
session_id = self.proto2session[proto]
del self.proto2session[proto]
if session_id in self.session2proto:
del self.session2proto[session_id]
def sendToAll(self,message,binary=False):
prepped = self.prepareMessage(message,binary)
for proto in self.proto2session.keys():
proto.sendPreparedMessage(prepped)
def run():
## WebSocket Factory
wsfactory = TrackingWebSocketFactory('ws://yourhostname:80')
wsfactory.protocol = TrackingWebSocketProtocol
wsresource = WebSocketResource(wsfactory)
## Modbus handler
modbus_thing = ModbusThing((addressofserver,portofserver))
modbus_thing.broadcast = wsfactory.sendToAll
modbus_thing.start()
## WebServer Site
# "static" subdirectory, containing http served resources, e.g. index.html, javascript and css
root = File("static")
# Your websocket service as 'ws://yourhostname/ws'
root.putChild("ws", wsresource)
site = Site(root)
reactor.listenTCP(80,site)
def main():
reactor.callWhenRunning(run)
reactor.run()
if __name__=='__main__':
main()
On the browser side of things. A little module for interacting with websockets is handy:
var FancyWebSocket = function(url){
var conn = null;
var fws = this;
if ("WebSocket" in window) {
conn = new WebSocket(url);
} else if ("MozWebSocket" in window) {
conn = new MozWebSocket(url);
} else {
console.log("Error Websockets not supported in browser");
return;
}
var callbacks = {};
var debug = true;
this.bind = function(event_name, callback){
callbacks[event_name] = callbacks[event_name] || [];
callbacks[event_name].push(callback);
return this;// chainable
};
this.send = function(event_name, event_data){
var payload = JSON.stringify({event:event_name, data: event_data});
conn.send( payload ); // <= send JSON data to socket server
return this;
};
this.close = function(){ conn.close(); return this;}
// dispatch to the right handlers
conn.onmessage = function(evt){
if (debug) console.log("Websocket(" + conn.URL + ") Message: " + evt.data)
var json = JSON.parse(evt.data)
dispatch(json.event, json.data)
};
conn.onclose = function(){
if (debug) console.log("Websocket(" + conn.URL + ") Closed");
dispatch('close',fws);
}
conn.onopen = function(){
if (debug) console.log("Websocket(" + conn.URL + ") Open");
dispatch('open',fws);
}
conn.onerror = function(e){
if (debug) console.log("Websocket(" + conn.URL + ") Error: " + error);
dispatch('error',fws,e);
}
this.setdebug = function(v) { debug=v; return this; }
var dispatch = function(event_name, message){
var chain = callbacks[event_name];
if(typeof chain == 'undefined') return; // no callbacks for this event
for(var i = 0; i < chain.length; i++){
chain[i]( message )
}
}
};
Then in your browser console:
conn = new FancyWebSocket("ws://yourhostname/ws");