0

I am working on a server that continuously send data to a client. This client may also interact punctuality with the server sending a specific request. I wrote a daemon to do this. Note that this daemon works in a thread. For now, the script is structured as follows :

class MyDaemon(threading.Thread):
 def __init__(self):
 # Init Stream socket (output) 
 self.MainSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 self.MainSock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 self.MainSock.bind(('', 15555))
 self.MainSock.listen(5)
 self.MainSock.setblocking(0)
 # Init Request socket (input)
 self.RequestSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 self.RequestSock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 self.RequestSock.bind(('', 15556))
 self.RequestSock.listen(5)
 self.RequestSock.setblocking(0)
 def run(self):
 while True:
 # Listen to connection on MainSock
 try:
 self.stream, address = self.MainSock.accept()
 except:
 pass
 # Listen to connection on RequestSock 
 try:
 self.request, address = self.RequestSock.accept()
 except:
 pass
 if self.stream:
 send_message_continuously() # it is a stream
 if self.request:
 recv_a_message_from_client()
 do_whatever_action_the client_request()

The problem is that :

  • using only the steamer, all works fine.

  • using only the requester, all works fine.

  • using the two sockets at the same time blocks the streamer.

I read that a single thread cannot connect (or be connected) to two sockets at the same time. I also read that the use of the select module may help to handle this kind of problem, but I never used it and I am a little bit lost about its use on my particular case.

What is the more efficient way to handle this problem ? How to set up selectin my particular case ? Wouldn't it be more efficent/simple to send stream to a sub-thread and request to another ?

EDIT : Finally, I used a sub-thread for the stream

asked Dec 11, 2016 at 9:59
1
  • FWIW, threads in python are about mere convenience, not efficiency (with some exceptions such as calling C modules that explicitly release the GIL). Commented Dec 11, 2016 at 10:48

2 Answers 2

2

When using select you have to test, which of your two sockets is ready to accept:

def run(self):
 while True:
 ready, _, _ = select.select([self.MainSock, self.RequestSock],[],[])
 for sock in ready:
 if sock is self.MainSock:
 send_message_continuously(sock.accept())
 elif sock is self.RequestSock:
 recv_a_message_from_client(sock.accept())
answered Dec 11, 2016 at 10:21
Sign up to request clarification or add additional context in comments.

2 Comments

Does the client has to use select too ?
If you want to process new incoming clients, while processing one client, yes. But then, it could be easier to use threads or some asyncio library.
1

I suggest to you to try gevent, simple to understant the api, its good to go if you want to overcome the problem, there is a section about servers to understand about tcp communication & rethink your current solution.
a code snap -

def handle(socket, address):
 print('new connection!')
server = StreamServer(('127.0.0.1', 1234), handle) # creates a new server
server.start() # start accepting new connections

Hope you can spend more time on making the application without making skelts. :)

answered Dec 11, 2016 at 10:07

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.