I've got a threaded server.
QTcpSocket needs to be created on the thread it needs to be ran on, FI: Qt - Handle QTcpSocket in a new thread by passing the socket descriptor.
My problem is that, I need to have a pool of thread and move the socket on a specific thread AFTER the client has sent a specific token which defines on which thread the socket needs to be.
In other words, I need to read the socket to know on which thread to place it beforehand.
Some idea would be to bind first to a QTcpSocket, read, then send the descriptor to the thread and create another QTcpSocket but the doc says:
Note: It is not possible to initialize two abstract sockets with the
same native socket descriptor.
Another solution is to create the socket in a separated thread and then join both thread together, though I don't know if that is possible.
Or perhaps be able to read the socket descriptor on the main thread before calling setSocketDescriptor on the child thread, if that is even possible?
You can absolutely easily move sockets across QThreads, just pay attention to four things:
1) Make sure your QTcpSocket does not have parent before you move
2) Disconnect everything from socket object before move
3) Connect anything you need back in a function which is running in a destination thread (you may use some sort of pool in a thread there those 'moved' objects stored before thread pick them up
4) Call readAll() after init as you may miss some readyRead() signals
Don't see any reasons not to do this if that fits design, at least I used it many times for multithreaded services to split sockets handlers across cores.
Related
How to pass a socket descriptor to another process through shared memory?
I pass the socket handle to control the process (getting there right handle value), then passes the handle of the control to another process which should continue to read from the descriptor (here get -1).
Important note: I'm not trying to write or read from the socket at the same time from different processes. I need to transfer the connection to another process without breaking the connection.
Thank you for your advice.
I have two QObjects A and B living in separate QThreads. A will emit a signal while B has a matching slot. I want to use connect() to connect A's signal to B's slot.
So the question is, is the connect() call thread safe? Does it matter in which of the two threads the connect is made?
Yes, QObject::connect() is thread safe method:
Note: All functions in this class are reentrant, but connect(),
connect(), disconnect(), and disconnect() are also thread-safe.
It doesn't matter from which thread you do the connection. But you should care about using of auto connection(default connection), unique connection or queued connection between your objects. And you should run event loops in both of your threads.
Also I strongly suggest you to check following articles: first, second.
I'm trying to understand the idea of non-blocking web server and it seems like there is something I miss.
I can understand there are several reasons for "block" web request(psuedocode):
CPU bound
string on_request(arg)
{
DO_SOME_HEAVY_CPU_CALC
return "done";
}
IO bound
string on_request(arg)
{
DO_A_CALL_TO_EXTERNAL_RESOURCE_SUCH_AS_WEB_IO
return "done";
}
sleep
string on_request(arg)
{
sleep(VERY_VERY_LONG_TIME);
return "done";
}
are all the three can benefit from non-blocking server?
how the situation that do benefit from the non-blocking web server really do that?
I mean, when looking at the Tornado server documentation, it seems
like it "free" the thread. I know that a thread can be put to sleep
and wait for a signal from the operation system (at least in Linux),
is this the meaning of "freeing" the thread? is this some higher
level implementation? something that actually create a new thread
that is waiting for new request instead of the "sleeping" one?
Am I missing something here?
Thanks
Basically the way the non-blocking sockets I/O work is by using polling and the state machine. So your scheme for many connections would be something like that:
Create many sockets and make them nonblocking
Switch the state of them to "connect"
Initiate the connect operation on each of them
Poll all of them until some events fire up
Process the fired up events (connection established or connection failed)
Switch the state those established to "sending"
Prepare the Web request in a buffer
Poll "sending" sockets for WRITE operation
send the data for those who got the WRITE event set
For those which have all the data sent, switch the state to "receiving"
Poll "receiving" sockets for READ operation
For those which have the READ event set, perform read and process the read data according to the protocol
Repeat if the protocol is bidirectional, or close the socket if it is not
Of course, at each stage you need to handle errors, and that the state of each socket is different (one may be connecting while another may be already reading).
Regarding polling I have posted an article about how different polling methods work here: http://www.ulduzsoft.com/2014/01/select-poll-epoll-practical-difference-for-system-architects/ - I suggest you check it.
To benefit from a non-blocking server, your code must also be non-blocking - you can't just run blocking code on a non-blocking server and expect better performance. For example, you must remove all calls to sleep() and replace them with non-blocking equivalents like IOLoop.add_timeout (which in turn involves restructuring your code to use callbacks or coroutines).
How To Use Linux epoll with Python http://scotdoyle.com/python-epoll-howto.html may give you some points about this topic.
I have a GUI program , that has a QLocalServer inside , each time it got a connection from client , it will popup a dialog asking user what to do.
But when there's multiple connection received simultaneously , a bunch of dialogs popus all together .. is there a way to queue them ?
I tried to use QMutex , but that stuck whole GUI thread.
What's the common / correct solution to this ?
Just use a queue data structure, i.e. put the incoming connections into a queue data structure and then whenever a dialog is closed (say) check if there are more connections on the queue; if yes, process next one. When you get a connection in and the queue is empty process it immediately. QMutex blocks the GUI thread because most likely you haven't spawned any additional threads, and it is actually a callback from QLocalServer and not a new thread that notifies you of an inbound connection.
What I am trying to solve: have an Erlang TCP server that listens on a specific port (the code should reside in some kind of external facing interface/API) and each incoming connection should be handled by a gen_server (that is even the gen_tcp:accept should be coded inside the gen_server), but I don't actually want to initially spawn a predefined number of processes that accepts an incoming connection). Is that somehow possible ?
Basic Procedure
You should have one static process (implemented as a gen_server or a custom process) that performs the following procedure:
Listens for incoming connections using gen_tcp:accept/1
Every time it returns a connection, tell a supervisor to spawn of a worker process (e.g. another gen_server process)
Get the pid for this process
Call gen_tcp:controlling_process/2 with the newly returned socket and that pid
Send the socket to that process
Note: You must do it in that order, otherwise the new process might use the socket before ownership has been handed over. If this is not done, the old process might get messages related to the socket when the new process has already taken over, resulting in dropped or mishandled packets.
The listening process should only have one responsibility, and that is spawning of workers for new connections. This process will block when calling gen_tcp:accept/1, which is fine because the started workers will handle ongoing connections concurrently. Blocking on accept ensure the quickest response time when new connections are initiated. If the process needs to do other things in-between, gen_tcp:accept/2 could be used with other actions interleaved between timeouts.
Scaling
You can have multiple processes waiting with gen_tcp:accept/1 on a single listening socket, further increasing concurrency and minimizing accept latency.
Another optimization would be to pre-start some socket workers to further minimize latency after accepting the new socket.
Third and final, would be to make your processes more lightweight by implementing the OTP design principles in your own custom processes using proc_lib (more info). However, this you should only do if you benchmark and come to the conclusion that it is the gen_server behavior that slows you down.
The issue with gen_tcp:accept is that it blocks, so if you call it within a gen_server, you block the server from receiving other messages. You can try to avoid this by passing a timeout but that ultimately amounts to a form of polling which is best avoided. Instead, you might try Kevin Smith's gen_nb_server instead; it uses an internal undocumented function prim_inet:async_accept and other prim_inet functions to avoid blocking.
You might want to check out http://github.com/oscarh/gen_tcpd and use the handle_connection function to convert the process you get to a gen_server.
You should use "prim_inet:async_accept(Listen_socket, -1)" as said by Steve.
Now the incoming connection would be accepted by your handle_info callback
(assuming you interface is also a gen_server) as you have used an asynchronous
accept call.
On accepting the connection you can spawn another ger_server(I would recommend
gen_fsm) and make that as the "controlling process" by calling
"gen_tcp:controlling_process(CliSocket, Pid of spwned process)".
After this all the data from socket would be received by that process
rather than by your interface code. Like that a new controlling process
would be spawned for another connection.