I/O Completion Port, How to free Per Socket Context and Per I/O Context? - iocp

I'm using IOCP on UDP socket, and the UDP socket may be closed in another thread. So, how can I free Per Socket Context and Per I/O Context which associated with SOCKET safely?
When I close the socket, there will still be un-completed I/O request in kernel queue.
If I free context just when socket closed, the GetQueueCompletionStatus may failed.
Now, my question is when to free context?

I use reference counting on all of my per socket and per I/O data structures. It makes this kind of thing easy as they are deleted when their references drop to 0. For some example code which shows one way to do this you could take a look at my free IOCP framework which you can download from here.

Use a mutex to enforce mutual exclusion in a critical section of your code that will check the availability of the socket, and open it if necessary. Lock the socket to that thread, and release it appropriately when finished.

I reuse my per-socket structures. After I have received completion events for all of the read and write operations that are required for that connection, I call TransmitFile with the TF_DISCONNECT and TF_REUSE_SOCKET flags to reset the socket without having to close it. I also reset the per-connection data once the completion event for the TransmitFile call comes through.

Close the socket first. You will get error (I think it is ERROR_OPERATION_ABORTED) from GetQueuedCompletionStatus, and then it is right time to free the structure. There are no other uncompleted requests on this connection in kernel queue by then, completion packets are maintained in FIFO order, and error packet will definitely be the last one for this connection.

Related

Retrieve struct epoll_event from socket that has not been triggered

I have dynamically allocated memory and stored it in a struct epoll_event which was then registered to a socket for epoll to monitor. There are times that I need to close this socket before the event has triggered. If I close the socket, the event and dynamically allocated memory is lost. Is there a way to retrieve it from epoll?
I have found a solution to my problem. If you are monitoring for EPOLLRDHUP, you can call shutdown(soc, SHUT_RDWR). This will trigger your socket and allow your handler to clean up. It would be nice to be able to trigger a socket without shutting down the connection, but I do not think that is possible.

Indy10 TCP client deliver reply to sending procedure

I am making a client program in Delphi 7 with Indy 10.
It must connect to the server with TIdTCPClient and keep alive the connection for sending and getting commands and replies until the program is closed.
The server can maintain only one constant connection per client to send info-messages.
TIdTCPClient is listening through a reading thread.
QUESTION:
I am sending a request to the server (using WriteLn) from some procedure to get a list of strings, for example. How can I get the answer (reply) for that request in the same procedure, without leaving it? Like using TIdHTTP.
I see 2 solutions:
making the request from one procedure and handle it in other - the code and logic will be more complicated.
for each request in a procedure, create a new TIdTCPClient (Connect, WriteLn, ReadLn, Disconnect, Free) and handle request. But I do not like this solution as it causes large overhead.
Since a reading thread is involved, it does complicate things a little. The reading thread needs to be the one to receive all of the replies and then it can dispatch them to handlers as needed.
Your first solution is fine, if you don't mind breaking up your code. This is the simplest solution, and the best one if the main thread is the one making the requests. You should never block the main thread.
As you mentioned, your second solution is not a very good one.
Another solution would be to create a TEvent for each request, and put each request into a list/queue somewhere. Have the reading thread find and signal the appropriate event when a response is received. The sending procedure can then wait on the event until it is signaled (TThread.Synchronize() works this way, for example). If the procedure is running in the main thread, use MsgWaitForMultipleObjects() to do the wait, so you can still service the main message queue while waiting.

Unordered socket read & close notification using IOCP

Most server framework/examples using sockets and I/O completion ports makes notifications in a way I couldn't completely figure out the purpose.
Upon read packets are processed, usually they are reordered to circumvent thread scheduling issues processing packets out of order no matter IOCP ensure a FIFO queue.
The problem is when a socket is closed gracefully or by an error. I saw in both situation, and again by the o.s. thread scheduler, the close notification may be sent to the application (i.e. http server using the framework) "before" the notification of data previously readed.
I think that the close notification should be queued in such way so the application receives it after previous reads.
Is there any intended use in most code I saw or my behavior may be correct depending on the situation?
What you suggest makes sense and I would imagine that any code that handles graceful close (a read returning 0 bytes) would do so by processing it after any proceeding successful read. Errors coming out of GetQueuedCompletionStatus(), such as connection reset errors, etc, are harder to integrate into the receive flow as they occur out of band as far as the receive data is concerned. Your question's a bit vague and depends very much on the code you're using and how you (or the people who wrote that code) want to handle these things. There is no single correct way, IMHO.

semaphore_wait_trap, GCD and CocoaAsyncSocket

I am currently building an App using CocoaAsyncSocket. I connect to a TCP server and read/write some data.
I create the socket using
self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
When data is received, I use FMDB to save it into a database. Everything works fine, until I send the App to Background (using Homebutton), and then resuming to it. The UI is frozen and not responsive, the Debugger shows, that it is waiting at semaphore_wait_trap.
Don't use the main queue as an argument to the delegateQueue parameter. Use one of the global concurrent queues or a serial/parallel queue you create yourself.
Update: I just looked at the implementation for GCDAsyncSocket and now realize that the delegate queue and methods are fired async to the actual read/write operations, which happen on an internal queue, so my suggestion was either irrelevant (depending on what you're actually doing in the completion methods) or, at the very least, not pertinent to the problem you're having. I think what's happening is that the internal socket(s) are being closed, as per the iOS App Programming Guide. To wit:
Be prepared to handle connection failures in your network-based
sockets. The system may tear down socket connections while your app
is suspended for any number of reasons. As long as your socket-based
code is prepared for other types of network failures, such as a lost
signal or network transition, this should not lead to any unusual
problems. When your app resumes, if it encounters a failure upon
using a socket, simply reestablish the connection.
The GCDAsyncSocket class you're using has some methods which seem to be aimed at dealing with this, such as -autoDisconnectOnClosedReadStream, and I think you just need to add some code to handle the disconnection / connection re-establishment case.

EAGAIN Error: Using Berkeley Socket API

Sometimes when I try to send some packets continuously( I am using the send() API ) I receive this error. Now I am not sure what should I do than. I have these questions:
1) Can I re-send again ? If yes then after how much time should I try again. Is there any particular strategy to be followed
2) Is buffer size has exceeded its limits is the only reason ?
3) Can someone please give me a better idea/code, how to handle such scenario.
Thanks.
Sambit.
From send(): "EAGAIN -- The socket is marked non-blocking and the requested operation would block." and also When the message does not fit into the send buffer of the socket, send normally blocks, unless the socket has been placed in non-blocking I/O mode. In non-blocking mode it would return EAGAIN in this case. The select(2) call may be used to determine when it is possible to send more data.
This thread has a simple example of using select() to deal with EAGAIN, and is followed by significant discussion about what sorts of surprises lurk beneath the surface.
EAGAIN is usually returned when there is no outbound buffer space left. How long to wait depends on the speed of the underlying connection. The normal way is to wait until select() or poll() tells you that the socket is available for writing. If on Linux, take a look at the select_tut(2) manpage, and of course the send(2) manpage.
You could change to blocking operation (which is the default) if you want the call to wait until there is space available. Or you could call select(2) to wait until the socket is writeable and then try again.
There is one other important consideration. If you are sending UDP packets, then keep in mind that there is no guarantee of congestion control, and if you're sending packets over the Internet you will almost certainly get packet loss if you just try sending UDP packets as fast as possible (this doesn't necessarily apply to other datagram sockets such as Unix sockets).

Resources