Python websocket server keeps closing - python-3.x

I made a very simple echo websocket server in python:
import asyncio
import websockets
clients = set()
async def server(websocket, path):
print("Client connected")
clients.add(websocket)
try:
async for message in websocket:
print(f"Received message: {message}")
# Echo message to all clients
for client in clients:
if client != websocket:
await client.send(message)
finally:
clients.remove(websocket)
print("Client disconnected")
start_server = websockets.serve(server, "0.0.0.0", 8080, ping_interval=11, ping_timeout=11)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
The problem is that after some seconds running, it closes with this exception:
raise self.connection_closed_exc()
websockets.exceptions.ConnectionClosedError: sent 1011 (unexpected error) keepalive ping timeout; no close frame received
Things I have tried:
send ping every 8 secs in the client app, still server closes
do not give ping_interval=11, ping_timeout=11 parameters in websockets.serve call so it runs forever
even shorter ping from client app every 5 secs
Nothing seems to work to keep the websocket connection permanently open.

Related

Problem connecting with external MQTT broker

I am using Ubuntu mate on the Pine A64+ 1Gb, I have installed paho mqtt library with python3, I tested library by creating local mosquito server and it is working fine. Now I need to connect to external broker having username and password, I tried with following code but it didn't worked for me. With this I am not even able to connect to the broker.
import paho.mqtt.client as mqtt
import time
broker_address = "121.242.232.175.xip.io"
port = 1883
def on_connect(client, userdata, flags, rc):
if rc==0:
client.connected_flag = True
print("connected OK Returned code=",rc)
else:
print("Bad connection Returned code=",rc)
mqtt.Client.connected_flag = False
client = mqtt.Client("SWAHVACAHU00000600")
client.username_pw_set(username="#####",password="#####")
client.on_connect = on_connect
client.loop_start()
client.connect(broker_address, port)
#while not client.connected_flag:
# print("inthe while")
# time.sleep(1)
client.loop_stop()
client.publish("pine", "Hello from Pinr A64",0)
client.disconnect()
I am checking on hivemqtt using as websocket client and subscribing to the same topic.
Check again what loop_start() does:
These functions implement a threaded interface to the network loop. Calling loop_start() once, before or after connect*(), runs a thread in the background to call loop() automatically. This frees up the main thread for other work that may be blocking. This call also handles reconnecting to the broker. Call loop_stop() to stop the background thread
paho-mqtt
That means that you start a thread which frequently handles all your networking actions (also sending your connection attempt). In your code you immediateley stop this thread again by calling loop_stop() - so there is a high chance that your connection attempt wasn't even send out.
In addition your main program terminates right after client.disconnect() without any delay - so the networking thread (if running) has absoluetly no time to deal anything at all
I recommend to restructure your code so your actions are properly timed and connection is closed after all work is done:
def on_connect(client, userdata, flags, rc):
if rc==0:
print("Connected.")
client.publish("mytopic/example", "")
else:
print("Connection refused, rc=",rc)
def on_disconnect(client, userdata, rc):
print ("Disconnected")
if rc != 0:
# otherwise loop_forever won't return
client.disconnect()
def on_publish(client, userdataq, mid):
print ("Message delivered - closing down connection")
client.disconnect()
print ("Program started")
client = mqtt.Client("MyClient")
client.username_pw_set(username=user,password=pw)
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.on_publish = on_publish
client.connect(broker_address, port)
client.loop_forever()
print("Program finished")
The blocking loop loop_forever() automatically returns if disconnect() is called. When using loop_start() / loop_stop() you need a loop by your own in order to prevent your program from terminating and you also have to handle when to break the loop and when to close the networking thread.
Also consider putting client.connect() within a try...except block

Flask-socketio doesn't recieve message from client

I'm trying to write a basic Socket.io program where the python client (python-socketio[asyncio_client] 4.6.0) emits a single string message to the flask server (with Flask-SocketIO 4.3.1 and eventlet).
The client appears to connect and send the message properly, but there is no output seen at the Flask server.
Server code:
from flask import Flask
from flask_socketio import SocketIO, emit
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
#socketio.on('connect')
def test_connect():
print('connected')
#socketio.on('disconnect')
def test_disconnect():
print('Client disconnected')
#socketio.on('message')
def handle_message(msg):
print('Recieved',msg)
#socketio.on('json')
def handle_json(json):
print(str(json))
if __name__ == '__main__':
socketio.run(app,debug=True)
Client code:
import asyncio
import socketio
sio = socketio.AsyncClient()
#sio.event
def connect():
print('connection established')
#sio.event
def disconnect():
print('disconnected from server')
async def main():
await sio.connect('http://localhost:5000')
await sio.emit('message',data='detection')
print('message sent')
await sio.disconnect()
if __name__ == '__main__':
asyncio.run(main())
Server output:
PS C:\Users\daksh\sih\sihPython> python .\test_socketio.py
* Restarting with stat
* Debugger is active!
* Debugger PIN: 101-561-255
(16664) wsgi starting up on http://127.0.0.1:5000
(16664) accepted ('127.0.0.1', 59497)
connected
127.0.0.1 - - [23/Jul/2020 20:38:42] "GET /socket.io/?transport=polling&EIO=3&t=1595516920.71801 HTTP/1.1" 200 367 0.004934
Client disconnected
127.0.0.1 - - [23/Jul/2020 20:38:42] "GET /socket.io/?transport=websocket&EIO=3&sid=88790300120f4b899e019ae7cc16ee87&t=1595516922.7757218 HTTP/1.1" 200 0 0.010027
Client output:
PS C:\Users\daksh\sih\sihPython> python .\socketio-client.py
connection established
message sent
The print statement from handle_message() is missing in the server output.
I've gone through multiple tutorials online, and I've tried it with and without namespaces. Have not been able to figure out what's wrong.
Any help is appreciated.
(I'm using Python 3.8.3 on Windows 10)
UPDATE: It works if I change the client code to use socketio.Client() instead of AsyncClient(), however I need the client to connect using AsyncClient.
The problem is that your async client is obviously asynchronous, you can't just send and exit because you don't give the background tasks that support the Socket.IO protocol time to do their thing.
Here is a more robust version of the client that lets the event go through before exiting:
import asyncio
import socketio
sio = socketio.AsyncClient()
#sio.event
async def connect():
print('connection established')
await sio.emit('message',data='detection', callback=done)
print('message sent')
#sio.event
def disconnect():
print('disconnected from server')
async def done():
await sio.disconnect()
async def main():
await sio.connect('http://localhost:5000')
await sio.wait()
if __name__ == '__main__':
asyncio.run(main())
The trick here is to use a callback on the emit. When the callback is invoked you are sure the message was delivered, so at that point it is safe to disconnect.

Python chat application

I am trying to write a simple chat server, that takes message from 1 user and sends to all other users. The other users can simultaneously send messages and receive them.
On client side one thread continuously waits for messages and other thread sends messages.
import socket
import threading
def getMessage(s):
while True:
s.send(raw_input("Message: "))
#Main
port = 1041
host = 'localhost'
s = socket.socket()
s.connect((host, port))
background_thread = threading.Thread(target=getMessage, args=(s,))
background_thread.daemon = True
background_thread.start()
while True:
print s.recv(1024)
On server side the server, takes the incoming connection request, opens a new thread for each new request and waits for their messages, when a connection sends a message, the server broadcasts it to all other connections that are open.
import socket
from thread import *
def ClientThread(connection, clients):
while True:
message = connection.recv(1024)
connection.send("Ack\n")
broadcast(connection, clients, message)
def broadcast(connection, clients, message):
for conn in clients:
if(conn != connection):
conn.send(message)
def AcceptConnections(clients):
while True:
connection, address = s.accept()
print "Got connection from ",connection
clients.append(connection)
start_new_thread(ClientThread, (connection, clients))
#Main
print "Started server"
port = 1041
host = 'localhost'
s = socket.socket()
s.bind((host, port))
s.listen(5)
clients = []
AcceptConnections(clients)
Expected: When one client sends a message, all other connected clients receive that message, irrespective of them typing and sending a message.
Reality: Other clients receive the message only after they send 1 or 2 messages.

Why doesn'e send() function return 0 in this situation?

i wrote a sample of socket,both server and client program.At server,when it accept the connection,it will close it at once.At client ,it will connect to server,then sleep for 1 secs,and then send something to server.
What confuse me is why send function doesn't return 0 ?The code is below
Client.py
import socket
import time
clientsocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
try:
clientsocket.connect(("127.0.0.1",8886))
ret = clientsocket.send(("Hello world").encode('utf-8'))
time.sleep(1.0)
print("All send bytes is {}".format(ret))
except socket.error as msg:
print(msg)
Server.py
import socket
serversocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
serversocket.bind(("127.0.0.1",8886))
serversocket.listen(5)
while True:
clientsocket,addr = serversocket.accept()
clientsocket.shutdown(2)
clientsocket.close()
Send function return 11 not 0.after connection established,i close it immediately.but client sends data successfully.that confuses me

Cannot create with async sub process for each socket connection with Python 3.5 asyncio

I am trying to create a socket server with asyncio where I would asynchronous listen for connection and get each connections incomming message. Howeven I cannot get it working.
Here is my code for server:
import asyncio
import socket, sys
from concurrent.futures import ProcessPoolExecutor
def print_output(csock, loop):
while 1:
print('gotcha')
msg = csock.recv(1024)
if not msg:
pass
else:
print ("Client send: " + msg)
def s_listen(loop):
while True:
(csock, adr) = sock.accept()
print('start another process')
asyncio.ensure_future(loop.run_in_executor(executor, print_output, csock, loop))
print('done')
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) #reuse tcp
sock.bind(('', 12345))
sock.listen(5)
executor = ProcessPoolExecutor()
loop = asyncio.get_event_loop()
listener = asyncio.ensure_future(loop.run_in_executor(executor,s_listen,loop))
print('here')
While this is my code for client
import socket, sys
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('', 12345))
sock.send(b"Hello I'm Client.\r\n")
I can get the function "s_listen" running asynchronously but the code got blocked by "print_output" function.
I am new to asyncio, can anyone help?
Thanks!
Asyncio provides a coroutine-based API called stream to manage socket clients and servers. Here's a modified version of the tcp echo server from the user documentation:
import asyncio
# Client handler
async def handle_echo(reader, writer):
while not reader.at_eof():
data = await reader.read(100)
message = data.decode().strip()
print('Client sent: ' + message)
writer.close()
# Start the server
loop = asyncio.get_event_loop()
coro = asyncio.start_server(handle_echo, '', 12345, loop=loop)
server = loop.run_until_complete(coro)
# Serve requests until Ctrl+C is pressed
print('Serving on {}'.format(server.sockets[0].getsockname()))
try:
loop.run_forever()
except KeyboardInterrupt:
pass
# Close the server
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
You can test this example with the netcat client:
# Client
$ ncat localhost 12345
hello,
world!
# Server
$ python3.5 server.py
Serving on ('0.0.0.0', 12345)
Client sent: hello,
Client sent: world!

Resources