0

I am currently working on a server application in C++. My main inspirations are these examples:

Windows SDK IOCP Excample

The I/O Completion Port IPv4/IPv6 Server Program Example

My app is strongly similar to these (socketobj, packageobj, ...).

In general, my app is running without issues. The only things which still causes me troubles are half open connections.

My strategy for this is: I check every connected client in a time period and count an "idle counter" up. If one completion occurs, I reset this timer. If the Idle counter goes too high, I set a boolean to prevent other threads from posting operations, and then call closesocket().

My assumption was that now the socket is closed, the pending operations will complete (maybe not instantly but after a time). This is also the behavior the MSDN documentation is describing (hints, second paragraph). I need this because only after all operations are completed can I free the resources.

Long story short: this is not the case for me. I did some tests with my testclient app and some cout and breakpoint debugging, and discovered that pending operations for closed sockets are not completing (even after waiting 10 min). I also already tried with a shutdown() call before the closesocket(), and both returned no error.

What am I doing wrong? Does this happen to anyone else? Is the MSDN documentation wrong? What are the alternatives?

I am currently thinking of the "linger" functionality, or to cancel every operation explicitly with the CancelIoEx() function

Edit: (thank you for your responses)

Yesterday evening I added a chained list for every sockedobj to hold the per io obj of the pending operations. With this I tried the CancelIOEx() function. The function returned 0 and GetLastError() returned ERROR_NOT_FOUND for most of the operations.

Is it then safe to just free the per Io Obj in this case?

I also discovered, that this is happening more often, when I run my server app and the client app on the same machine. It happens from time to time, that the server is then not able to complete write operations. I thought that this is happening because the client side receive buffer gets to full. (The client side does not stop to receive data!).

Code snipped follows as soon as possible.

Woife
  • 27
  • 8
  • Please provide a [mcve]. – Harry Johnston Oct 12 '17 at 13:46
  • If the receiver doesn't receive, *of course* the sender will block, unless he's in non-blocking mode, which IOCP isn't. You test is not valid. – user207421 Oct 13 '17 at 07:14
  • @EJP Does that mean, I have no possibility to detect this beforehand? It seems that the `WSASend()` can be posted, but it will never complete. How can I improve the Test? – Woife Oct 13 '17 at 09:19
  • `ERROR_NOT_FOUND` probably means that there isn't any pending I/O on the sockets in question. Which probably means that either Windows or your code has dropped the original completion notifications, it is significantly more likely to be your code. – Harry Johnston Oct 13 '17 at 11:18
  • Your test client has to read everything available on the socket. – user207421 Oct 13 '17 at 15:31
  • when the last handle to socket is closed and he bind to iocp - all io operations on it canceled (how minimum begin from win7) and this is not safe and fatal error just free the per Io Obj before io complete – RbMm Oct 18 '17 at 23:07

1 Answers1

1
  • The 'linger' setting can used to reset the connection, but that way you will (a) lose data and (b) deliver a reset to the peer, which may terrify it.
  • If you're thinking of a positive linger timeout, it doesn't really help.
  • Shutdown for read should terminate read operations, but shutdown for write only gets queued after pending writes so it doesn't help at all.
  • If pending writes are the problem, and not completing, they will have to be cancelled.
user207421
  • 305,947
  • 44
  • 307
  • 483
  • Thank you for your answer. I would not care for dataloss. My applications intention is that the clients should normally connected "forever" and send the same data cyclical so if a client loses connection and leaves a half open socket I have no problem with just kill it. What for me is imporant: the application should be able to recover the memory and everything in order to go on normally. What do you mean by "terrify the peer"? – Woife Oct 12 '17 at 07:21
  • Hang on. If the client closes the connection, a `read()` by the server will return -1, whereupon you close the channel. You don't have to take any special measures about that at all: it is just a normal part of network programming. 'Terrify the peer' means that it will get a connection reset instead of the usual end of stream as just described: but if it's the client that's doing the closing, that doesn't apply, of course. It seemed to me that the only way your I/O operations wouldn't complete must be if they were pending writes. Now it merely appears you have a bug in your read-handling code. – user207421 Oct 12 '17 at 11:49
  • Sorry for this very long response time. In the end it was like you all suggested: I was the problem. The function of the `closesocket()` is as intended. I had one time the issue were one connection was not ended properly but i could not reproduce it. I marked this as answer because is think it is a nice summary of the mentioned possibilitys. One thing i wanted to add: If you develop a IOCP app, you should also take care of partial sends (because they should normally not happen) and kill the connection if this happens. In most of the examples noone cares about this but it is important. – Woife Nov 24 '17 at 08:41