Python socket "receive data disallowed error" - python-3.x

I have the following code and it's giving me this error in Python3 in Windows:
OSError: [WinError 10057] A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Could someone help explain why i'm getting this error and how I can avoid it? What I want to do is start 5 threads with different socket numbers and have them do non-blocking receives. Thx in advance.
import threading
import socket
import os
import errno
import sys
from time import sleep
HOST = '127.0.0.1' # Standard loopback interface address (localhost)
def worker(port):
"""thread worker function"""
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.setblocking(False)
s.bind((HOST, port))
s.listen()
print('Thread is listening on', port)
while True:
try:
msg = s.recv(4096)
except socket.timeout as e:
err = e.args[0]
if err == 'timed out':
sleep(1)
print ('No data available')
continue
else:
# a "real" error occurred
print (e)
sys.exit(1)
else:
print (msg)
threads = []
for i in range(10001, 10005):
t = threading.Thread(target=worker(i))
threads.append(t)
t.start()
for thread in threads:
thread.join()

Related

Can't stop aiohttp websocket server

I can't cancel my aiohttp websocket server from within the application. I want to stop the server and shutdown when I get a "cancel" string
from the client. Yes, I get it, and I finish my co-routine (websocket_handler), but there are three co-routines from the aiohttp library which still continue working.
Of course, I can invoke asyncio.get_event_loop().stop() at the end of my co-routine, but is there a graceful way for stopping aiohttp server?
From my code one can see that I've tried to use Application().on_shutdown.append(), but it failed.
What is the right way?
#!/usr/bin/env python
# -- coding: utf-8 --
import os
import asyncio
import signal
import weakref
import aiohttp.web
from aiohttp import ClientConnectionError, WSCloseCode
# This restores the default Ctrl+C signal handler, which just kills the process
#https://stackoverflow.com/questions/27480967/why-does-the-asyncios-event-loop-suppress-the-keyboardinterrupt-on-windows
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
HOST = os.getenv('HOST', 'localhost')
PORT = int(os.getenv('PORT', 8881))
async def testhandle(request):
#Сопрограмма одрабатывающая http-запрос по адресу "http://127.0.0.1:8881/test"
print("server: into testhandle()")
return aiohttp.web.Response(text='Test handle')
async def websocket_handler(request):
#Сопрограмма одрабатывающая ws-запрос по адресу "http://127.0.0.1:8881"
print('Websocket connection starting')
ws = aiohttp.web.WebSocketResponse()
await ws.prepare(request)
request.app['websockets'].add(ws)
print('Websocket connection ready')
try:
async for msg in ws:
if msg.type == aiohttp.WSMsgType.TEXT:
if msg.data == 'close':
print(msg.data)
break
else:
print(msg.data)
await ws.send_str("You said: {}".format(msg.data))
elif msg.type == aiohttp.WSMsgType.ERROR:
print('ws connection closed with exception %s' %
ws.exception())
except (asyncio.CancelledError, ClientConnectionError):
pass # Тут оказываемся когда, клиент отвалился.
# В будущем можно тут освобождать ресурсы.
finally:
print('Websocket connection closed')
request.app['websockets'].discard(ws)
#pending = asyncio.Task.all_tasks()
#asyncio.get_event_loop().stop()
return ws
async def on_shutdown(app):
for ws in set(app['websockets']):
await ws.close(code=WSCloseCode.GOING_AWAY, message='Server shutdown')
def main():
loop = asyncio.get_event_loop()
app = aiohttp.web.Application()
app['websockets'] = weakref.WeakSet()
app.on_shutdown.append(on_shutdown)
app.add_routes([aiohttp.web.get('/', websocket_handler)]) #, aiohttp.web.get('/test', testhandle)
try:
aiohttp.web.run_app(app, host=HOST, port=PORT, handle_signals=True)
print("after run_app")
except Exception as exc:
print ("in exception")
finally:
loop.close()
if __name__ == '__main__':
main()
I believe the correct answer is simply:
raise aiohttp.web.GracefulExit()
After catching the exception, it calls all the handlers appended to the on_shutdown and on_cleanup signals and dies.
One can see in the source code the aiohttp.web.run_app() waits for two exceptions: GracefulExit and KeyboardInterrupt. While the latter is rather uninteresting, following the trace of GracefulExit can lead you to this place in web_runner.py, that registers SIGINT and SIGTERM signal handlers to a function with raise GracefulExit().
Indeed, I also managed to gracefully shut it down by raising the signal.SIGINT or signal.SIGTERM from itself, e.g.
import signal
signal.raise_signal(signal.SIGINT)
This was tested to work on Fedora Linux 34, Python 3.9.7, aiohttp 3.7.4.
https://docs.aiohttp.org/en/v3.0.1/web_reference.html#aiohttp.web.Application.shutdown
app.shutdown()
app.cleanup()
After shutdown you should also do cleanup()

how does python pick the ports to be used in sockets

i cant understand why each time python chooses different port for me even i have specified a static port ,for example last output was :
Server waiting for connection...
Client connected from: ('127.0.0.1', 52480)
here is the code for both client and server side ,just don't know how python does that and also if there a way to impose on python to use port i have set
server
import socket
import threading
def sendMsg(conn):
while True:
msg = input()
conn.send(msg.encode('utf-8'))
def recvMsg(conn):
while True:
msg = conn.recv(1024)
print(msg.decode('utf-8'))
if __name__ == '__main__':
server_socket = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
server_socket.bind(('127.0.0.1', 8000))
server_socket.listen(5)
print('Server waiting for connection...')
client_sock, addr = server_socket.accept()
print('Client connected from: ', addr)
obj1 = threading.Thread(None, target=sendMsg, args=(client_sock,))
obj2 = threading.Thread(None, target=recvMsg, args=(client_sock,))
obj1.start()
obj2.start()
obj1.join()
obj2.join()
client_sock.close()
server_socket.close()
client side
import socket
import threading
def sendMsg(conn):
while True:
msg = input()
conn.send(msg.encode('utf-8'))
def recvMsg(conn):
while True:
msg = conn.recv(1024)
print(msg.decode('utf-8'))
if __name__ == '__main__':
client_sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock_addr= ('127.0.0.1',8000)
client_sock.connect(sock_addr)
obj1 = threading.Thread(None, target=sendMsg, args=(client_sock,))
obj2 = threading.Thread(None, target=recvMsg, args=(client_sock,))
obj1.start()
obj2.start()
obj1.join()
obj2.join()
print('Socket is closed!!!')
client_sock.close()

python3: two clients sending data to server using sockets

I'm working with 3 raspberry pi, one as a server and the two others are clients. What I want to do is to make the clients communicate with the server simultaneously, I don't want to wait for client1 communication to be done in order to launch client2 request to the server (which I succeeded to do). However, I want each client to send different data to server at the same time. I tried to use Sockets and threading, like below.
server code:
import socket
import RPi.GPIO as GPIO
from threading import Thread
# Multithreaded Python server : TCP Server Socket Thread Pool
class ClientThread(Thread):
def __init__(self,ip,port):
Thread.__init__(self)
self.ip = ip
self.port = port
print ("[+] New server socket thread started for " + ip + ":" + str(port))
def run(self):
while True :
data = conn.recv(2048)
data = data.decode('utf-8')
print ("Server received data:", data)
MESSAGE = input("Multithreaded Python server : Enter Response from Server/Enter exit:")
if MESSAGE == 'exit':
break
conn.send(str.encode(MESSAGE)) # echo
# Multithreaded Python server : TCP Server Socket Program Stub
TCP_IP = ''
TCP_PORT = 9050
BUFFER_SIZE = 2000 # Usually 1024, but we need quick response
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(2)
threads = []
list_data=[]
while True:
print ("Multithreaded Python server : Waiting for connections from TCP clients...")
(conn, (ip,port)) = s.accept()
data = conn.recv(2048)
newthread = ClientThread(ip,port)
newthread.start()
threads.append(newthread)
list_data.append(data)
for t in threads:
t.join()
client1 code:
import socket
import RPi.GPIO as GPIO
import time
host = '192.168.0.198'
port = 9050
BUFFER_SIZE = 2000
MESSAGE = input("tcpClient1: Enter message/ Enter exit:")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
while MESSAGE != 'exit':
s.send(str.encode(MESSAGE))
data = s.recv(BUFFER_SIZE)
data = data.decode('utf-8')
print (" Client2 received data:", data)
MESSAGE = input("tcpClient2: Enter message to continue/ Enter exit:")
client2 code:
import socket
import RPi.GPIO as GPIO
import time
import socket
host = '192.168.0.198'
port = 9050
BUFFER_SIZE = 2000
MESSAGE = input("tcpClient2: Enter message/ Enter exit:")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
while MESSAGE != 'exit':
s.send(str.encode(MESSAGE))
data = s.recv(BUFFER_SIZE)
data = data.decode('utf-8')
print (" Client received data:", data)
MESSAGE = input("tcpClient2: Enter message to continue/ Enter exit:")
when i run, i obtain:
in the server terminal:
Multithreaded Python server : Waiting for connections from TCP clients...
[+] New server socket thread started for 192.168.0.197:47012
Multithreaded Python server : Waiting for connections from TCP clients...
[+] New server socket thread started for 192.168.0.196:47886
Multithreaded Python server : Waiting for connections from TCP clients...
in client1 terminal:
tcpClient1: Enter message/ Enter exit:begin
in client2 terminal:
tcpClient2: Enter message/ Enter exit:begin
It seems like server didn't receive or send any data.
As #Hikke mentioned in his comment, your server receives at two different places. The conn.recv call in this code snippet eats up the data that the server receiving thread is expecting. Remove data = conn.recv(2048) in your server's main loop:
while True:
print ("Multithreaded Python server : Waiting for connections from TCP clients...")
(conn, (ip,port)) = s.accept()
data = conn.recv(2048) # <== dont eat the data of your thread here!
newthread = ClientThread(ip,port)
newthread.start()
threads.append(newthread)
list_data.append(data)

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