Why does putting a socket in a queue close it? - python

I'm writing a server that operates with a fixed number of workers, each with different properties (in the snippet below, n is such a property.
Upon getting a request, I would like to put it into a queue, so the first available worker can deal with the task.
Unfortunately, the socket gets closed when it's enqueued.
import threading
from queue import Queue
import socketserver
thread = True
queue = Queue()
class BasicHandler(socketserver.BaseRequestHandler):
def handle(self):
while True:
sock = self.request
byte = sock.recv(10)
print(byte)
class ThreadedHandler(socketserver.BaseRequestHandler):
def handle(self):
queue.put(self.request)
def worker(n):
print('Started worker ' + str(n))
while True:
sock = queue.get()
byte = sock.recv(10)
print(byte)
if thread:
[threading.Thread(target=worker, args=(n,)).start() for n in range(2)]
handler = ThreadedHandler
else:
handler = BasicHandler
socketserver.TCPServer.allow_reuse_address = True
server = socketserver.TCPServer(("localhost", 9999), handler)
server.serve_forever()
Running the above snippet with thread = False works as fine, but when I try to connect to the thread = True version, telnet immediately says:
Connection closed by foreign host.
and the server prints:
Started worker 0
Started worker 1
b''

The request is automatically closed, when the method ThreadedHandler.handler finished. You have to override TCPServer.shutdown_request if you want to keep the socket open.

Related

Python: how to create a server to supervise a thread pool?

I have a thread pool that handles some tasks concurrently. Now I'd like the tasks (multiply_by_2 here) to print something before exit.
Originally, I created a lock and passed the lock to each worker thread. If a thread wants to print something, it first acquires the lock, prints its message to stdout, then releases the lock.
Now, I want to have a dedicated event-driven server thread to handle the printing. If a thread wants to print something, it just send its message to that server, via a Unix domain socket (AF_UNIX). I hope in this way, each thread's blocking time can be reduced (no need to wait for the lock) and I don't need to share a lock among worker threads. The server thread just prints whatever messages it got from clients (i.e. the worker threads) in order.
I tried for some time with Python's asyncio module (requiring Python 3.7+) but couldn't figure it out. How should I do it?
This cleaned-up template is:
# Python 3.7+
import asyncio
import multiprocessing.dummy as mp # Threading wrapped using multiprocessing API.
import os
import socket
import sys
import threading
import time
server_address = './uds_socket' # UNIX domain socket
def run_multiple_clients_until_complete(input_list):
pool = mp.Pool(8)
result_list = pool.map(multiply_by_2, input_list)
return result_list
def multiply_by_2(n):
time.sleep(0.2) # Simulates some blocking call.
message_str = "client: n = %d" % n
# TODO send message_str.encode() to server
return n * 2
# Server's callback when it gets a client connection
# If you want to change it, please do..
def client_connected_cb(
stream_reader: asyncio.StreamReader,
stream_writer: asyncio.StreamWriter) -> None:
message_str = reader.read().decode()
print(message_str)
def create_server_thread():
pass # TODO
# Let the server finish handling all connections it got, then
# stop the server and join the thread
def stop_server_and_wait_thread(thread):
pass # TODO
def work(input_list):
thread = create_server_thread()
result_list = run_multiple_clients_until_complete(input_list)
stop_server_and_wait_thread(thread)
return result_list
def main():
input_list = list(range(20))
result_list = work(input_list)
print(result_list)
if __name__ == "__main__":
sys.exit(main())
Some extra requirements:
Don't make async: run_multiple_clients_until_complete(), multiply_by_2(), main().
It would be nicer to use the SOCK_DGRAM UDP protocol instead of SOCK_STREAM TCP, but it's unnecessary.

Multithreaded TCP socket

I'm trying to create a threaded TCP socket server that can handle multiple socket request at a time.
To test it, I launch several thread in the client side to see if my server can handle it. The first socket is printed successfully but I get a [Errno 32] Broken pipe for the others.
I don't know how to avoid it.
import threading
import socketserver
import graphitesend
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
data = self.request.recv(1024)
if data != "":
print(data)
class ThreadedTCPServer(socketserver.ThreadingTCPServer):
allow_reuse_address = True
def __init__(self, host, port):
socketserver.ThreadingTCPServer.__init__(self, (host, port), ThreadedTCPRequestHandler)
def stop(self):
self.server_close()
self.shutdown()
def start(self):
threading.Thread(target=self._on_started).start()
def _on_started(self):
self.serve_forever()
def client(g):
g.send("test", 1)
if __name__ == "__main__":
HOST, PORT = "localhost", 2003
server = ThreadedTCPServer(HOST, PORT)
server.start()
g = graphitesend.init(graphite_server = HOST, graphite_port = PORT)
threading.Thread(target = client, args=(g,)).start()
threading.Thread(target = client, args=(g,)).start()
threading.Thread(target = client, args=(g,)).start()
threading.Thread(target = client, args=(g,)).start()
threading.Thread(target = client, args=(g,)).start()
threading.Thread(target = client, args=(g,)).start()
threading.Thread(target = client, args=(g,)).start()
server.stop()
It's a little bit difficult to determine what exactly you're expecting to happen, but I think the proximate cause is that you aren't giving your clients time to run before killing the server.
When you construct a Thread object and call its start method, you're creating a thread, and getting it ready to run. It will then be placed on the "runnable" task queue on your system, but it will be competing with your main thread and all your other threads (and indeed all other tasks on the same machine) for CPU time.
Your multiple threads (main plus others) are also likely being serialized by the python interpreter's GIL (Global Interpreter Lock -- assuming you're using the "standard" CPython) which means they may not have even gotten "out of the gate" yet.
But then you're shutting down the server with server_close() before they've had a chance to send anything. That's consistent with the "Broken Pipe" error: your remaining clients are attempting to write to a socket that has been closed by the "remote" end.
You should collect the thread objects as you create them and put them in a list (so that you can reference them later). When you're finished creating and starting all of them, then go back through the list and call the .join method on each thread object. This will ensure that the thread has had a chance to finish. Only then should you shut down the server. Something like this:
threads = []
for n in range(7):
th = threading.Thread(target=client, args=(g,))
th.start()
threads.append(th)
# All threads created. Wait for them to finish.
for th in threads:
th.join()
server.stop()
One other thing to note is that all of your clients are sharing the same single connection to send to the server, so that your server will never create more than one thread: as far as it's concerned, there is only a single client. You should probably move the graphitesend.init into the client function if you actually want separate connections for each client.
(Disclaimer: I know nothing about graphitesend except what I could glean in a 15 second glance at the first result in google; I'm assuming it's basically just a wrapper around a TCP connection.)

How to get notified the latest recv in socket(python)

sock.setblocking(0)
ready = select.select([sock], [], [], timeout)
try:
if ready[0]:
status = sock.recv(1024)
return status
else:
print "Time out Occured, Disconnecting..."
I have socket receive function which receives whenever some status gets changed in client side. Meanwhile, I will process other activities.
since I get the sock receive between some other activities I miss that receive and could not process that receive.
so how could I get latest receive whenever I want!
please note am a newbie in python.
If you need background IO, spawning a new thread to handle IO is probably the easiest method:
import socket
import threading
import queue
class ClientReceiver(threading.Thread):
RECV_BUF_SIZE = 1024
QUEUE_SIZE = 2
def __init__(self, sock, recv_buf_size=None, queue_size=None, *args, **kwargs):
super(ClientReceiver, self).__init__(*args, **kwargs)
# set thread as daemon thread, we don't want to
# wait for this thread on interpreter exit.
self.setDaemon(True)
self.sock = sock
self.recv_buf_size = recv_buf_size or self.RECV_BUF_SIZE
self.queue_size = queue_size or self.QUEUE_SIZE
def run(self):
sock = self.sock
try:
while True:
data = sock.recv(self.recv_buf_size)
self.queue.put(data)
except Exception as ex:
# handle errors
raise
# Usage example:
sock = ...
receiver = ClientReceiver(sock)
receiver.start()
data = receiver.queue.get(block=False)
The thread retrieves data from the network as soon as it is available and puts it into a queue. The thread blocks if the queue is full, you may or may not want another strategy.
Retrieve data from the queue at any time using receiver.queue.
This is missing code for proper client socket shutdown, but you probably get the basic idea.

ZMQ: REQ/REP fails with multiple concurrent requests and polling

I have run into a strange behaviour with ZeroMQ that I have been trying to debug the whole day now.
Here is a minimal example script which reproduces the problem. It can be run with Python3.
One server with a REP socket is started and five clients with REP sockets connect to it basically simultaneously. The result is that the server starts to block for some reason after the first few messages. It seems like the poller.poll(1000) is what blocks indefinitely.
This behavior also seems to be timing-dependant. Insert a sleep(0.1) in the loop that starts the clients and it works as expected.
I would have expected the REP socket to queue all incoming messages and release them one after the other via sock.recv_multipart().
What is happening here?
import logging
from threading import Thread
from time import sleep
import zmq
logging.basicConfig(level=logging.INFO)
PORT = "3446"
stop_flag = False
def server():
logging.info("started server")
context = zmq.Context()
sock = context.socket(zmq.REP)
sock.bind("tcp://*:" + PORT)
logging.info("bound server")
poller = zmq.Poller()
poller.register(sock, zmq.POLLIN)
while not stop_flag:
socks = dict(poller.poll(1000))
if socks.get(sock) == zmq.POLLIN:
request = sock.recv_multipart()
logging.info("received %s", request)
# sleep(0.5)
sock.send_multipart(["reply".encode()] + request)
sock.close()
def client(name:str):
context = zmq.Context()
sock = context.socket(zmq.REQ)
sock.connect("tcp://localhost:" + PORT)
sock.send_multipart([name.encode()])
logging.info(sock.recv_multipart())
sock.close()
logging.info("starting server")
server_thread = Thread(target=server)
server_thread.start()
sleep(1)
nr_of_clients = 5
for i in range(nr_of_clients):
Thread(target=client, args=[str(i)]).start()
stop_flag = True
For me the problem seems to be that you are "shutting down" the server before all clients have received their reply. So I guess its not the server who's blocking but clients are.
You can solve this by either waiting some time before you set the stop_flag:
sleep(5)
stop_flag = True
or, better, you explicitely join the client threads like:
nr_of_clients = 5
threads = []
for i in range(nr_of_clients):
thread = Thread(target=client, args=[str(i)])
thread.start()
threads.append(thread)
for thread in threads:
thread.join()
stop_flag = True

Python thread blocking further execution

I have been trying to write a python script that initiates a thread to listen on a socket and send HTTP data to another application to be launched by the same program. There is a requirement for the socket server to be running prior to executing the application. However, the thread running the socket server blocks further execution of the program and it freezes where it is listening. Putting some dummy code.
In module 1:
def runServer(Port, Host, q):
HTTPServerObj = HTTPServer((Host, Port), RequestHandler)
HTTPServerObj.handle_request()
HTTPServerObj.server_close()
q.put((True, {'messageDoNotDuplicate': 'Data sent successfully by the server'}))
class SpoofHTTPServer(object):
def runServerThread(self):
q = Queue.Queue()
serverThread=Thread(target=runServer, args=(self.Port, self.Host, q))
serverThread.daemon=True
serverThread.start()
result = q.get()
print result
return result
In module 2:
from module1 import SpoofHTTPServer
spoofHTTPServer = SpoofHTTPServer()
result = spoofHTTPServer.runServerThread()
rc = myApp.start()
The myApp.start() never gets executed as the thread is blocking it.
It looks to me like the method that blocks execution is not the thread but q.get(). It will listen to the Queue until an item is available, but since it's executed before running the client application nothing ever gets posted into the queue. Maybe you should return q instead and listen to the queue in module 2 after calling myApp.start()?
This may work for you from Python 3. Make a connection to ('localhost', 8080) to see it work.
import queue as Queue
from threading import Thread
from http.server import HTTPServer
from socketserver import BaseRequestHandler as RequestHandler
def runServer(Port, Host, q):
HTTPServerObj = HTTPServer((Host, Port), RequestHandler)
HTTPServerObj.handle_request()
HTTPServerObj.server_close()
q.put((True, {'messageDoNotDuplicate':
'Data sent successfully by the server'}))
class SpoofHTTPServer(object):
Port = 8080
Host = ''
def runServerThread(self):
q = Queue.Queue()
serverThread=Thread(target=runServer, args=(self.Port, self.Host, q))
serverThread.daemon=True
serverThread.start()
result = q.get()
print(result)
return result
spoofHTTPServer = SpoofHTTPServer()
result = spoofHTTPServer.runServerThread()
##rc = myApp.start()

Categories

Resources