Configure the Time-Out function for CSocket CSocket operations, such as send (), received (), and connect () are blocked operations, that is, they will not return before successful or error occurs. In some cases, an operation may never be successful, and the program will be looped forever in order to wait for its completion. Limiting a successful completion of a successful time in a program is a good idea. This article is to discuss this issue. One way is to design a timer that triggers when the operating fee is too long. The key to this approach is how to deal with the timer. Although the operation is "blocked", it still has the ability to handle the ability to return. If you set the timer with setTimer, you can intercept the WM_TIMER message when it is generated. The main functions involving this process are: Windows API :: SetTimer (), MFC Function CSocket :: OnMessagepending () and CSocket :: CancelBlockingCall (). These features can be simplified in your CSocket class. Types in the class: BOOL setTimeout (uint utimeout) it should be called before the CSocket function call. Utimeout is in a thousand seconds. The following implementation is just a simple setting timer. Returns false when the set timer fails. See the description of SetTimer in the Windows API. Bool KillTimeout () This function should be called when the operation is not completed. It removes the timer set by SetTimeout. Returns false if the Call KillTimer fails. See the description of KillTimer in the Windows API. Bool OnMessagepending () It is a virtual callback function that is called by the CSocket class when the wait is complete. It gives you the opportunity to process the message. This time we use it to check the timer set by SetTimeout, if time-out, it calls CancelBlockingCall (). See the MFC documentation about OnMessagepending () and CancelBlockingCall (). Note CancelBlockingCall () will make the current operation fails, the getLastError () function returns WSAEINTR (pointing out is an interrupt operation). Here is an example of using this class: ...
CtimeOutsocket SockServer;
Cacceptedsocket sockaccept;
SOCKSERVER.CREATE (777);
SockServer.Listen ();
// Note The Following Sequence:
// settimeout
//
// killtimeout
IF (! SOCKSERVER.SETTIMEOUT (10000))
{
Assert (false);
// Error Handling ... for Some Reason, We Could Not Setup
// the time.
}
IF (! SOCKSERVER.ACCEPT (SOCKACCEPT))
{
INT NERROR = getLastError ();
IF (Nerror == WSAEINTR)
AfxMessageBox ("No Connections Arrived for 10 Seconds);
Else
// DO Other Error Processing.
}
IF (! SOCKSERVER.KILLTIMEOUT ())
{
Assert (false);
// Error Handling ... for Some Reason the Timer Could Not
// be destroyed ... Perhaps a Memory Overwrite Has Changed
// m_ntimerid? //
}
...
Here is sample code: //
//Header File
//
Class CtimeOutsocket: Public Csocket
{
PUBLIC:
Bool setTimeout;
Bool killtimeout ();
protected:
Virtual Bool OnMessagepending ();
Private:
INT m_ntimerid;
}
//
// end of file
//
//
// Implementation File
//
Bool ctimeoutsocket :: onMessagepending ()
{
MSG msg;
IF (: PeekMessage (& MSG, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE))
{
IF (msg.wparam == (uint) m_ntimerid)
{
// Remove the message and call cancelblockingcall.
:: PeekMessage (& MSG, NULL, WM_TIMER, WM_TIMER, PM_REMOVE);
CancelBlockingCall ();
Return False; // no need for idle time processing.
}
}
Return Csocket :: onMessagepending ();
}
Bool CTimeOutsocket :: SetTimeout (uint utimeout)
{
M_ntimerid = setTimer (NULL, 0, Utimeout, NULL);
Return M_NTIMERID;
}
Bool ctimeoutsocket :: killtimeout ()
{
Return KillTimer (NULL, M_NTIMERID);
}