• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1669
  • Last Modified:

MFC CSocket Connect() hangs.

I'm having a problem with CSocket that I can't resolve, it seems easy enough and probably is but I'm completely stuck.
I have a server and a client application, the client contacts the server when it needs data, the data is sent using the MFC classes CFileSocket, CArchive and CSocket and the size of the data is between 10 KB and 2000 KB depending on what is requested.

The code snippet below shows where the problem is:

1      if (!socket.Create())
2            throw CMyException(_T("socket.Create"), socket.GetLastError());
4      if (!socket.Connect(server, port))            // HANGS!
5            throw CMyException(_T("socket.Connect"), socket.GetLastError());

The program doesn't always hang on row 4, usually it hangs after 2-3 requests, if I restart the server it works fine again.
Interestingly, if I put a breaktpoint on row 4 and wait a while or step into socket.Connect() everything works fine so it seems like there is some timing problem.
Another interesting thing I have noticed is that if I send small pieces of data the program doesn't hang, perhaps it will hang if I repeat the process many,many times but there is no indication of it as I far as I can tell.
  • 3
  • 3
1 Solution
In my opinion you should NEVER use a blocking Connect() call in your Windows application.  Connect() can hang indefinitely and you have no way of knowing if/when it might do so.

My suggestion is to stop using the CSocket class altogether and redesign your application with CAsyncSocket instead.  Then if/when this happens you can wait for an appropriate period of time (5-10 sec), cancel the non-responding connect call and retry the connection.

Yes, using async sockets is more complex but I assure you your users will appreciate the fact that your application will still be responsive when a connect/read/write operation on a socket hangs due to any number of reasons.
PramboAuthor Commented:
The reason I use CSocket is that I don't want the complexity of CAsyncSocket because the request is serial by nature (i.e. Web request->COM->CSocket->Thread->CSocket). If I would use CAsyncSocket I would have to either poll for completion or implement the same functionality as in CSocket and nothing has been gained.
I have thought about your suggestion before but have been too lazy to try it out but I'll give it a go.
No, you would not, and in fact, SHOULD NOT, poll for completion.  Your application should be designed to receive a notification message when the status of the socket changes.  If you poll you will end up with the same problem you have now, namely that the application will hang while waiting for the socket.

And YES, MUCH is gained.  The specific problem you are having is solved as well as other problems that I've mentioned.

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

PramboAuthor Commented:
I have solved the problem by using the CTimeOutSocket class as outlined in http://support.microsoft.com/kb/q138692/.
When the call hangs on Connect() it gets cancelled automatically after a set period of time and I retry, there haven't been any need to retry more than once on any instance.
More or less the solution looks like:

1     if (!socket.Create())
2          throw CMyException(_T("socket.Create"), socket.GetLastError());
4     socket.SetTimeOut(5*1000);
4     if (!socket.Connect(server, port))
5          throw CMyException(_T("socket.Connect"), socket.GetLastError());
6     socket.KillTimeOut();

The code above is wrapped inside a try-catch and do-while which repeats the Connect() call if the first call wasn't successful.
The reason I didn't want to use CAsyncSocket in the first place is that I would have to rewrite a lot of code that was using CArchive and CSocketFile and that didn't appeal at all. I'll still award jhance all the points because I think his statement made me think about my solution in the first place and his solution would probably have worked if I had the time to change the main implementation.
There are problems, severe in my opinion, with this band-aid approach.
PramboAuthor Commented:
The reason I gave a C is that the solution suggested is not what I asked for and something I already had considered. I did think about using the CTimeOutSocket class though after jhance's suggestion, to quote:  "Then if/when this happens you can wait for an appropriate period of time (5-10 sec), cancel the non-responding connect call and retry the connection", I do exactly as he suggests but using CTimeOutSocket instead of CAsyncSocket and therefore I rewarded him the points.
To quote the grading criteria: "or if the answers, after clarification, lack finality or do not completely address the issue presented, then a "C" grade is an option".
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

  • 3
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now