I want to use Overlapped I/O with Completion Routine to handle client connections.
In my UI thread I want to use WSASend(), but in order for the system to call my callback function to inform me that data has been sent, the UI thread must be in a wait state, but this will freeze my UI!
How should I fix this problem?
I agree with #DavidHeffernan - the UI thread should be doing UI things. The IO thread surely needs a binding and port, (server), or peer address and port(client). The socket from ConnectEx or AcceptEx is surely better loaded in the IO thread, but a Socket class with, (at this time, undefined), socket member could surely be created in the UI thread and signaled into the IO thread for handling. Whether buffers form part of your Socket class, or a separate Buffer class, is a design consideration.
One implementation, (that I have used successfully):
Design/define an 'Inter Thread Comms', (ITC'), message class. This has a 'command' enum member that can tell other threads to do stuff, together with any other useful stuff that might be required in such a message
Derive a 'Socket' class from ITC. This has string members for the IP/port, the socket handle and anything else that may be required.
Derive a 'Buffer' class from ITC. This has a 'BoundSocket' member, buffer-space and an 'OVERLAPPED' struct.
Comms with the IO thread is fairly easy. Since it has to wait on something altertably, it can wait on a semaphore that manages a 'Commands' ConcurrentQueue.
If you UI wishes to instruct the IO thread to, say, connect to a server, it creates a Socket instance, (new), loads the IP and Port members from UI elements, sets the Command enum to 'Connect', pushes the socket onto the Commands queue and signals the semaphore, (ReleaseSemaphore).
The alertable wait in the IO thread then returns with WAIT_OBJECT_0, (it needs to ignore returns with WAIT_IO_COMPLETION) and so knows that a command has ben queued. It pops it from the Commands queue and acts upon the command enum, (maybe switching on it), to perform the required action/s. For connect, this would involve an overlapped 'ConnectEx' call to queue up a connect request and set up the connect completion handler.
The connect completion handler, when called, checks for a succesfull connect and, if so, could new up a Buffer, load it, issue a WSARecv with it for the server to send stuff and store the returned Socket object in a container. If failed, it could load the Socket
with a suitable error message and PostMessage it back to the UI thread to inform the user of the fail.
See - it's not that difficult and does not need 10000 lines of code:)
The only thing I don't know how to do immediately is getting the 'this' for the socket object back from the OVERLAPPED struct that is returned in the completion routine. On 32-bit systems, I shoved the Buffer 'this' into the hEvent field of the overlapped struct in the Buffer instance and cast it back in the completion routine. The Buffer instance has a Socket reference, so the job was done. On 64-bit systems, hEvent has not enough room to store the 48/64-bit 'this' Buffer pointer and, (aparrently), this required an extended OVERLAPPED struct:( Not sure how that is done - maybe you will find out:)
[edit] #BenVoigt has advice on the 32/64 bit 'getting the Socket context 'this' back in the completion routine' issue - it's easier than I thought:):
https://stackoverflow.com/a/28660537/758133
Related
I am going to write a program processing requests coming from a TCP/IP connection and from a shared memory queue at the same time. This means that the program shall block until there is either a request in the queue or an input on a socket. Then it will process the request and continue. Is there a way to do this in a single thread? I mean some kind of select working with a semaphore and socket at the same time. Latency is important in my case and I do not want to do a busy wait neither. The program will run on Windows. Thanks.
One way is to use overlapped I/O and using the hEvent mechanism to signal I/O completion. You can then wait on both the queue semaphore and the hEvent/s with the WaitForMultipleObjects() API.
Another way is to use overlapped I/O and completion routines. You could then wait on the semaphore in a loop with the WaitForSingleObectEx() API with the bAlertable argument set true so that the thread can process the queued completion routines, eg:
while(WAIT_IO_COMPLETION!=WaitForSingleObjectEx(queueSema,INFINITE,true)){
[deque object and handle it];
};
Both schemes allow you to set timeouts to poll the server to keep the connection open and/or check if it's down.
Libevent is a way to abstract out I/O events, and it has a way to manually trigger an event.
Setting up file-based events with libevents looks like this (copied from the documentation):
void callback_func(evutil_socket_t fd, short what, void *arg) { ... }
struct event *ev1, *ev2;
struct event_base *base = event_base_new();
/* The caller has already set up fd1, fd2 somehow, and make them
nonblocking. */
ev1 = event_new(base, fd1, EV_TIMEOUT|EV_READ|EV_PERSIST, callback_func,
(char*)"Reading event");
ev2 = event_new(base, fd2, EV_WRITE|EV_PERSIST, callback_func,
(char*)"Writing event");
event_add(ev1, NULL);
event_add(ev2, NULL);
If you want to create an event not associated with any file descriptor, pass -1 intead of an fd:
ev = event_new(base, -1, EV_PERSIST | EV_READ, callback_func, NULL);
event_add(ev, NULL);
Now, instead of raising a semaphore, trigger the event:
event_active(ev, EV_WRITE, 0);
The Windows way of waiting for one of several possible things to happen is WaitForMultipleObjectsEx. You give it an array of Windows "handles" which can become "signaled" (these kinds of handles are called Synchronization Objects), and when any of them is signaled, the function returns and tells you which one it was.
The problem is that a socket, as implemented in the WinSock library, is not a Windows handle. You can't put it into the WaitForMultipleObjectsEx array.
Luckily, WinSock provides a function WSAEventSelect that can link a socket to a Windows event object. An event object is the simplest type of synchronization object. In this case, you would ask it to signal the event object when the socket is ready to be read (FD_READ). Then you would put the event object into the array alongside the semaphore.
The Windows Semaphore is already a synchronization object -- see CreateSemaphore in MSDN. It is signaled when its count is greater than 0. (This is what you expect from a semaphore.)
If you don't understand the whole idea of Synchronization Objects and reading MSDN doesn't help, I'd recommend Jim Beveridge's book Multithreading Applications In Win32. It's an old book, so it doesn't have sockets or semaphores in it, but it explains how to work with event objects, mutexes, and WaitForMultipleObjects in general; the sockets and semaphores will be easy to understand then.
I'm looking for some information on what happens when sending at the same time on a WSA socket that had been duplicated? Is that safe? Can you point me to any specific docs?
Do I need to have some sort of message across the processes to tell which process to be active for sends? I assume I have to do that for receives.
Can anyone give me an example of what this portion of the documentation means?
Notification on shared sockets is subject to the usual constraints of WSAAsyncSelect and WSAEventSelect. Issuing either of these calls using any of the shared descriptors cancels any previous event registration for the socket, regardless of which descriptor was used to make that registration. Thus, a shared socket cannot deliver FD_READ events to process A and FD_WRITE events to process B. For situations when such tight coordination is required, developers would be advised to use threads instead of separate processes.
As the documentation states:
The descriptors that reference a shared socket can be used independently for I/O. However, the Windows Sockets interface does not implement any type of access control, so it is up to the processes involved to coordinate their operations on a shared socket. Shared sockets are typically used to having one process that is responsible for creating sockets and establishing connections, and other processes that are responsible for information exchange.
If you have two processes sending on a shared socket at the same time, they are going to overlap each other. The same as if two threads within a single process send to the same socket at the same time. So you need to coordinate the sends to avoid the overlap. You can use a shared named mutex for that, for instance.
As for the quote you asked about, it should be self-explanatory if you read the relevant documentation:
WSAAsyncSelect() function
Issuing a WSAAsyncSelect for a socket cancels any previous WSAAsyncSelect or WSAEventSelect for the same socket. For example, to receive notification for both reading and writing, the application must call WSAAsyncSelect with both FD_READ and FD_WRITE, as follows:
rc = WSAAsyncSelect(s, hWnd, wMsg, FD_READ|FD_WRITE);
It is not possible to specify different messages for different events. The following code will not work; the second call will cancel the effects of the first, and only FD_WRITE events will be reported with message wMsg2:
rc = WSAAsyncSelect(s, hWnd, wMsg1, FD_READ);
rc = WSAAsyncSelect(s, hWnd, wMsg2, FD_WRITE);
WSAEventSelect() function
Issuing a WSAEventSelect for a socket cancels any previous WSAAsyncSelect or WSAEventSelect for the same socket and clears the internal network event record. For example, to associate an event object with both reading and writing network events, the application must call WSAEventSelect with both FD_READ and FD_WRITE, as follows:
rc = WSAEventSelect(s, hEventObject, FD_READ|FD_WRITE);
It is not possible to specify different event objects for different network events. The following code will not work; the second call will cancel the effects of the first, and only the FD_WRITE network event will be associated with hEventObject2:
rc = WSAEventSelect(s, hEventObject1, FD_READ);
rc = WSAEventSelect(s, hEventObject2, FD_WRITE); //bad
So, if you have process S sharing a socket with processes A and B, you can't have A listening for FD_READ events and B listening for FD_WRITE events, or vice versa. It is an all-or-nothing deal.
It is as safe as writing to the same socket from two threads. The actual send() function is atomic: no-one else can enter it for the same socket while you're in it. So you won't get data interleaving, provided you are writing entire messages with a single send(), and you're in blocking mode: see comments below.
Only if you're violating the condition above.
It implies that really only one of the processes can use select() on that socket concurrently. As soon as one process does that, the other process loses its 'interest' in whatever it was selecting on, so none of those events will fire. This is usually exactly what you want, as you don't want both processes reacting to the same read event. However it's more problematic if you're also selecting on write. If you're not selecting at all, don't worry about this.
I have a MFC DLL that I am implementing. The main thread creates a progress bar (CProgressCtrl) and then starts a CWinThread to perform some socket operation. The idea is to have the main thread update the progress bar while the other thread performs sendto socket operation (data request) to request data. Here is the issue though, due to legacy implementation, the receive capability is done via overriding OnReceive function of CAsyncSocket. When OnReceive is called, the code simply copies the data into its own buffer and allow another function to process later.
Currently, the other thread that is doing the sendto operation (data request) is activity checking the buffer to see if the sequence number has been incremented. This all worked fine when the sendto operation is within the main thread (this means UI will freeze), but after I relocated the sendto operations to another thread, the OnReceive is no longer being called even when the data is sent from the other software(verified).
My question is that why is OnReceive not being called when the other side is clearly sending data? I understand this might not be the optimal design but due to legacy design, i would like to keep the current design.
CASyncSocket is bound to the thread in which it is created. Only that thread can receive the OnReceive notification.
Hey I am not sure if this has already been asked that way. (I didn´t find anwsers to this specific questions, at least). But:
I have a program, which - at startup - creates an Login-window in a new UI-Thread.
In this window the user can enter data which has to be verified by an server.
Because the window shall still be responsive to the users actions, it (ofc it´s only a UI-thread) shall not handle the transmission and evaluation in it´s own thread.
I want the UI-thread to delegate this work back to the main thread.
In addition: The main thread (My "client" thread) shall manage all actions that go on, like logging in, handle received messages from the server etc... (not window messages)
But I am not sure of how to do this:
1.) Shall I let the UI-Thread Queue an APC to the main thread (but then the main thread does not know about the stuff going on.
2.) May I better use event objects to be waited on and queues to transmit the data from one thread to another?...
Or are there way better options?
For example: I start the client:
1. The client loads data from a file and does some intialization
The client creates a window in a new thread which handles login data input from the user.
The Window Thread shall notifiy and handle the , that has been entered by the user, over to the client.
The Client shall now pack the data and delegate the sending work to another object (e.g. CSingleConnection) which handles sending the data over a network (of course this does not require a new thread, because it can be handle with Overlapped I/O...
One special receiver thread receives the data from the server and handles it back to the client, which - in turn - evaluates the data.
If the data was correct and some special stuff was received from the server, the main thread shall signal the UI thread to close the window and terminate...
The client then creates a new window, which will handle the chatting-UI
The chatting UI thread and the Client thread shall communicate to handle messages to be sent and received...
(Hope this helps to get what I am trying)...
It all depends on what you are prepared to use. If you are developing with Qt, their signals and slots are just the thing to do such a communication. They also supply a network library, so you could easily omit the receiver thread because their network classes do asynchronous communication and will send a signal when you have data, which means your thread does not need to be blocked in the mean time.
If you don't want to use Qt, boost also supplies thread safe signals and slots, but as far as I understand it their slots will be run in the context of the calling thread...
Anyways, I have used Qt sig and slots with great satisfaction for exactly this purpose. I wholeheartedly agree GUI's shouldn't freeze, ever.
I don´t know wether this is good style or not (anwsering Your own question):
But I think I go with Event Objects and two queues (one for the connection between Client and Connection, and one to communicate Client and UI)...
My program uses a NetworkOutput object which can be used to write data to a remote server. The semantic is that in case the object is currently connected (because there is a remote server), then the data is actually sent over the socket. Otherwise, it's silently discarded. Some code sketch:
class NetworkOutput
{
public:
/* Constructs a NetworkOutput object; this constructor should not block, but it
* should start attempting to the given host/port in the background.
*
* In case the connection gets closed for some reason, the object should immediately
* try reconnecting.
*/
NetworkOutput( const std::string &hostName, unsigned short port );
/* Tells whether there is a remote client connected to this NetworkOutput object.
* Clients can use this function to determine whether they need to both serializing
* any data at all before calling the write() function below.
*/
bool isConnected() const;
/* Write data to the remote client, if any. In case this object is not connected
* yet, the function should return immediately. Otherwise it should block until
* all data has been written.
*
* This function must be thread-safe.
*/
void write( const std::vector<char> &data );
};
Right now, I have this implemented using nonblocking sockets. I'n the NetworkOutput constructor, I'm creating a TCP socket as well as an internal helper window. I then do a WSAAsyncSelect call on the socket. This makes the socket nonblocking, and it will cause a magic window message (which I registered myself) to be sent to the internal helper window in case any interesting event (such as 'connection established' or 'connection closed') happens on the socket. Finally, I start a connection attempt using WSAConnect. This returns immediately, and the window procedure of my internal helper window will get notified as soon as the connection succeeded. In case the connection is closed (because the remote client went away), the message procedure will be called and I will attempt to reconnect.
This system allows the me to attach and detach a remote client at will. It works quite well, but unfortunately it requires that I have a message loop running. Without the message loop, the notifications sent by the WSAAsyncSelect call don't seem to arrive at my helper window.
Is there any way to implement a class as described above without requiring a message loop? I was toying around with using blocking sockets in a helper thread, but I couldn't come up with anything reasonable yet. I also considered using a UDP socket, so that I don't even need to connect at all, but I'd like to know whether there is a remote client listening so that in case there is no remote client, the clients of the NetworkOutput class don't need to do any serialization work of complex objects before they can call write().
You can use WSAEventSelect instead of WSAASyncSelect, which takes the handle of a WSAEVENT instead of a message ID, and then use WSAWaitForMultipleEvents to wait for the event to be signalled.
Instead of WSAEVENT you can also use normal Win32 events created with CreateEvent, and the normal synchronisation functions such as WaitForMultipleObjects.
You are looking for the select function:
http://support.sas.com/documentation/onlinedoc/sasc/doc750/html/lr2/select.htm
Basically you specify a set of ports you want to listen to.
When called the select deschedules the thread (thus allowing other threads to work while you do a non busy wait). Your thread is woken up after either a time limit (usually infinite) a signal (if you want to manually make the thread or the system does) or there is some input that needs to be handled on any of the ports.
When your thread wakes up it is usually best to let another thread handle the work so; what usually happens is that you create a work object for each port that has data waiting to be read and add these to a queue where a set of worker threads than start handling the input. Once this is done you call select() again to wait for more input.
Note: You don't have to do this it can be done in a single thread.