有关MFC中CSocket类超时存在的BUG,讨论!!!

masterlee 2001-05-28 09:41:00
本人在使用CSocket类的过程中发现超时问题很难控制。
在MFC中提到如下:


FIX: CSocket Operation Hangs if a Timer is Active
Last reviewed: September 19, 1997
Article ID: Q154649
The information in this article applies to:
The Microsoft Foundation Classes (MFC) included with: Microsoft Visual C++, 32-bit Edition, version 4.2


SYMPTOMS
A call to CSocket Connect, Accept, Send, or Receive hangs if a timer is active.



CAUSE
CSocket operations are written using "pseudo-blocking." The WinSock API call is not a true blocking call, but if it doesn't return immediately then CSocket will call PumpMessages. PumpMessages looks for the FD_xxx notification and the CSocket function will not return until the FD_xxx notification arrives.

PumpMessages will not detect the socket notification if a timer is active because it looks for WM_TIMER messages first. When a WM_TIMER message arrives, the function doesn't look any further for other messages.

The PumpMessages function is looking for WM_TIMER messages because it sets up its own timer to cause the application to retry its socket calls and do periodic idle-time processing while waiting for the socket notification.



RESOLUTION
There are two possible resolutions:


Disable all timers while making CSocket calls.

Override the PumpMessages function so that it only looks for its own WM_TIMER messages and does not pick up other timer messages. This can be done by borrowing the CSocket::PumpMessages function from SOCKCORE.CPP and changing it as follows:
#if _MFC_VER == 0x0420


#define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE
#define WM_SOCKET_NOTIFY 0x0373
#define WM_SOCKET_DEAD 0x0374

#define _afxSockThreadState AfxGetModuleThreadState()

#endif

BOOL CMySocket::PumpMessages(UINT uStopFlag)
{
#if _MFC_VER != 0x0420
return CSocket::PumpMessages(uStopFlag);
#else

// The same socket better not be blocking in more than one place.
ASSERT(m_pbBlocking == NULL);

_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;

ASSERT(pState->m_hSocketWindow != NULL);

BOOL bBlocking = TRUE;
m_pbBlocking = &bBlocking;
CWinThread* pThread = AfxGetThread();

// This is not a timeout in the WinSock sense, but more
// like a WM_KICKIDLE to keep message pumping alive
UINT nTimerID = ::SetTimer(pState->m_hSocketWindow, 0,
m_nTimeOut, NULL);

if (nTimerID == 0)
AfxThrowResourceException();

BOOL bPeek = TRUE;

while (bBlocking)
{
TRY
{
MSG msg;
if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_SOCKET_NOTIFY, WM_SOCKET_DEAD, PM_REMOVE))
{
if (msg.message == WM_SOCKET_NOTIFY &&
(SOCKET)msg.wParam == m_hSocket)
{
if (WSAGETSELECTEVENT(msg.lParam) == FD_CLOSE)
{
break;
}
if (WSAGETSELECTEVENT(msg.lParam) == uStopFlag)
{
if (uStopFlag == FD_CONNECT)
m_nConnectError = WSAGETSELECTERROR(msg.lParam);
break;
}
}
if (msg.wParam != 0 || msg.lParam != 0)
CSocket::AuxQueueAdd(msg.message, msg.wParam, msg.lParam);

bPeek = TRUE;
}
else if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_TIMER, WM_TIMER, PM_REMOVE))
{
break;
}

if (bPeek && ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (OnMessagePending())
{
// allow user-interface updates
pThread->OnIdle(-1);
}
else
{
bPeek = FALSE;
}
}
else
{
// no work to do -- allow CPU to sleep
WaitMessage();
bPeek = TRUE;
}
}
CATCH_ALL(e)
{
TRACE0("Error: caught exception in PumpMessage - continuing.\n");
bPeek = TRUE;
}
END_CATCH_ALL
}

::KillTimer(pState->m_hSocketWindow, nTimerID);

if (!bBlocking)
{
WSASetLastError(WSAEINTR);
return FALSE;
}
m_pbBlocking = NULL;

::PostMessage(pState->m_hSocketWindow,WM_SOCKET_NOTIFY,0,0);

return TRUE;

#endif // _MFC_VER
}


STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This bug has been fixed with the Visual C++ 4.2b patch. For more information on this patch, please see the following articles in the Microsoft Knowledge Base:


ARTICLE-ID: Q156934
TITLE : PATCH: Visual C++ 4.2b Patch

ARTICLE-ID: Q160491
TITLE : Information on Files Modified by VC42b Patch: Part 1 of 4

ARTICLE-ID: Q160496
TITLE : Information on Files Modified by VC42b Patch: Part 2 of 4

ARTICLE-ID: Q160505
TITLE : Information on Files Modified by VC42b Patch: Part 3 of 4

ARTICLE-ID: Q160506
TITLE : Information on Files Modified by VC42b Patch: Part 4 of 4




--------------------------------------------------------------------------------

Additional query words: CAsyncSocket CSocket hangs timer
Keywords : MfcSockets vcbuglist420 vcfixlist420 kbnetwork kbprg kbbuglist kbfixlist
Technology : kbMfc
Version : 4.2
Platform : NT WINDOWS
Issue type : kbbug
Solution Type : kbfix


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.


Last reviewed: September 19, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.


...全文
214 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
masterlee 2001-05-28
  • 打赏
  • 举报
回复

CSDN首页 | 新闻聚焦 | 共享软件 | 俱乐部 | 开发文档 | 专家门诊 | 招聘求职 | Linux园地 | 程序员杂志
--------------------------------------------------------------------------------

我要回复 | 打印贴子 | 推荐给朋友 | 关闭窗口

主  题:有关MFC中CSocket类超时存在的BUG,讨论!!!
作  者:masterlee
所属论坛:Visual C++
问题点数:20
回复次数:0
人气指数:0
发表时间:2001-5-28 9:41:00

本人在使用CSocket类的过程中发现超时问题很难控制。
在MFC中提到如下:


FIX: CSocket Operation Hangs if a Timer is Active
Last reviewed: September 19, 1997
Article ID: Q154649
The information in this article applies to:
The Microsoft Foundation Classes (MFC) included with: Microsoft Visual C++, 32-bit Edition, version 4.2


SYMPTOMS
A call to CSocket Connect, Accept, Send, or Receive hangs if a timer is active.



CAUSE
CSocket operations are written using "pseudo-blocking." The WinSock API call is not a true blocking call, but if it doesn't return immediately then CSocket will call PumpMessages. PumpMessages looks for the FD_xxx notification and the CSocket function will not return until the FD_xxx notification arrives.

PumpMessages will not detect the socket notification if a timer is active because it looks for WM_TIMER messages first. When a WM_TIMER message arrives, the function doesn't look any further for other messages.

The PumpMessages function is looking for WM_TIMER messages because it sets up its own timer to cause the application to retry its socket calls and do periodic idle-time processing while waiting for the socket notification.



RESOLUTION
There are two possible resolutions:


Disable all timers while making CSocket calls.

Override the PumpMessages function so that it only looks for its own WM_TIMER messages and does not pick up other timer messages. This can be done by borrowing the CSocket::PumpMessages function from SOCKCORE.CPP and changing it as follows:
#if _MFC_VER == 0x0420


#define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE
#define WM_SOCKET_NOTIFY 0x0373
#define WM_SOCKET_DEAD 0x0374

#define _afxSockThreadState AfxGetModuleThreadState()

#endif

BOOL CMySocket::PumpMessages(UINT uStopFlag)
{
#if _MFC_VER != 0x0420
return CSocket::PumpMessages(uStopFlag);
#else

// The same socket better not be blocking in more than one place.
ASSERT(m_pbBlocking == NULL);

_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;

ASSERT(pState->m_hSocketWindow != NULL);

BOOL bBlocking = TRUE;
m_pbBlocking = &bBlocking;
CWinThread* pThread = AfxGetThread();

// This is not a timeout in the WinSock sense, but more
// like a WM_KICKIDLE to keep message pumping alive
UINT nTimerID = ::SetTimer(pState->m_hSocketWindow, 0,
m_nTimeOut, NULL);

if (nTimerID == 0)
AfxThrowResourceException();

BOOL bPeek = TRUE;

while (bBlocking)
{
TRY
{
MSG msg;
if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_SOCKET_NOTIFY, WM_SOCKET_DEAD, PM_REMOVE))
{
if (msg.message == WM_SOCKET_NOTIFY &&
(SOCKET)msg.wParam == m_hSocket)
{
if (WSAGETSELECTEVENT(msg.lParam) == FD_CLOSE)
{
break;
}
if (WSAGETSELECTEVENT(msg.lParam) == uStopFlag)
{
if (uStopFlag == FD_CONNECT)
m_nConnectError = WSAGETSELECTERROR(msg.lParam);
break;
}
}
if (msg.wParam != 0 ¦¦ msg.lParam != 0)
CSocket::AuxQueueAdd(msg.message, msg.wParam, msg.lParam);

bPeek = TRUE;
}
else if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_TIMER, WM_TIMER, PM_REMOVE))
{
break;
}

if (bPeek && ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (OnMessagePending())
{
// allow user-interface updates
pThread->OnIdle(-1);
}
else
{
bPeek = FALSE;
}
}
else
{
// no work to do -- allow CPU to sleep
WaitMessage();
bPeek = TRUE;
}
}
CATCH_ALL(e)
{
TRACE0("Error: caught exception in PumpMessage - continuing.\n");
bPeek = TRUE;
}
END_CATCH_ALL
}

::KillTimer(pState->m_hSocketWindow, nTimerID);

if (!bBlocking)
{
WSASetLastError(WSAEINTR);
return FALSE;
}
m_pbBlocking = NULL;

::PostMessage(pState->m_hSocketWindow,WM_SOCKET_NOTIFY,0,0);

return TRUE;

#endif // _MFC_VER
}


STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This bug has been fixed with the Visual C++ 4.2b patch. For more information on this patch, please see the following articles in the Microsoft Knowledge Base:


ARTICLE-ID: Q156934
TITLE : PATCH: Visual C++ 4.2b Patch

ARTICLE-ID: Q160491
TITLE : Information on Files Modified by VC42b Patch: Part 1 of 4

ARTICLE-ID: Q160496
TITLE : Information on Files Modified by VC42b Patch: Part 2 of 4

ARTICLE-ID: Q160505
TITLE : Information on Files Modified by VC42b Patch: Part 3 of 4

ARTICLE-ID: Q160506
TITLE : Information on Files Modified by VC42b Patch: Part 4 of 4




--------------------------------------------------------------------------------

Additional query words: CAsyncSocket CSocket hangs timer
Keywords : MfcSockets vcbuglist420 vcfixlist420 kbnetwork kbprg kbbuglist kbfixlist
Technology : kbMfc
Version : 4.2
Platform : NT WINDOWS
Issue type : kbbug
Solution Type : kbfix


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.


Last reviewed: September 19, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.




转移贴子到 Visual C++ Visual Basic Delphi C/C++ C++ Builder ASM 数据库开发 PowerBuilder ActiveX/COM 数据算法 软件工程 图形/游戏/多媒体 安全技术 网络/通讯 技术书籍 文件格式 C# XML 数据仓库 主页制作 图形处理 ASP PHP Perl Java Javascript JSP 软件使用 资源使用 软件注册 我看软件 寻找软件 行业软件 软件评测 Windows 95/98 Windows NT/2000 DOS Linux/Unix 硬件指南 程序人生 软件市场 程序员考试 人才热线 建议和意见 灌水乐园 走向海外 程序员杂志 | 贴子加分 | 删除贴子


回复贴子:


--------------------------------------------------------------------------------

我要回复: 有人参与讨论这个问题,请用EMail通知我


返回问题 | 关闭窗口





美达美简介 广告服务 英语步步高 程序员大本营 百联美达美科技有限公司 版权所有




masterlee 2001-05-28
  • 打赏
  • 举报
回复

CSDN首页 | 新闻聚焦 | 共享软件 | 俱乐部 | 开发文档 | 专家门诊 | 招聘求职 | Linux园地 | 程序员杂志
--------------------------------------------------------------------------------

我要回复 | 打印贴子 | 推荐给朋友 | 关闭窗口

主  题:有关MFC中CSocket类超时存在的BUG,讨论!!!
作  者:masterlee
所属论坛:Visual C++
问题点数:20
回复次数:0
人气指数:0
发表时间:2001-5-28 9:41:00

本人在使用CSocket类的过程中发现超时问题很难控制。
在MFC中提到如下:


FIX: CSocket Operation Hangs if a Timer is Active
Last reviewed: September 19, 1997
Article ID: Q154649
The information in this article applies to:
The Microsoft Foundation Classes (MFC) included with: Microsoft Visual C++, 32-bit Edition, version 4.2


SYMPTOMS
A call to CSocket Connect, Accept, Send, or Receive hangs if a timer is active.



CAUSE
CSocket operations are written using "pseudo-blocking." The WinSock API call is not a true blocking call, but if it doesn't return immediately then CSocket will call PumpMessages. PumpMessages looks for the FD_xxx notification and the CSocket function will not return until the FD_xxx notification arrives.

PumpMessages will not detect the socket notification if a timer is active because it looks for WM_TIMER messages first. When a WM_TIMER message arrives, the function doesn't look any further for other messages.

The PumpMessages function is looking for WM_TIMER messages because it sets up its own timer to cause the application to retry its socket calls and do periodic idle-time processing while waiting for the socket notification.



RESOLUTION
There are two possible resolutions:


Disable all timers while making CSocket calls.

Override the PumpMessages function so that it only looks for its own WM_TIMER messages and does not pick up other timer messages. This can be done by borrowing the CSocket::PumpMessages function from SOCKCORE.CPP and changing it as follows:
#if _MFC_VER == 0x0420


#define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE
#define WM_SOCKET_NOTIFY 0x0373
#define WM_SOCKET_DEAD 0x0374

#define _afxSockThreadState AfxGetModuleThreadState()

#endif

BOOL CMySocket::PumpMessages(UINT uStopFlag)
{
#if _MFC_VER != 0x0420
return CSocket::PumpMessages(uStopFlag);
#else

// The same socket better not be blocking in more than one place.
ASSERT(m_pbBlocking == NULL);

_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;

ASSERT(pState->m_hSocketWindow != NULL);

BOOL bBlocking = TRUE;
m_pbBlocking = &bBlocking;
CWinThread* pThread = AfxGetThread();

// This is not a timeout in the WinSock sense, but more
// like a WM_KICKIDLE to keep message pumping alive
UINT nTimerID = ::SetTimer(pState->m_hSocketWindow, 0,
m_nTimeOut, NULL);

if (nTimerID == 0)
AfxThrowResourceException();

BOOL bPeek = TRUE;

while (bBlocking)
{
TRY
{
MSG msg;
if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_SOCKET_NOTIFY, WM_SOCKET_DEAD, PM_REMOVE))
{
if (msg.message == WM_SOCKET_NOTIFY &&
(SOCKET)msg.wParam == m_hSocket)
{
if (WSAGETSELECTEVENT(msg.lParam) == FD_CLOSE)
{
break;
}
if (WSAGETSELECTEVENT(msg.lParam) == uStopFlag)
{
if (uStopFlag == FD_CONNECT)
m_nConnectError = WSAGETSELECTERROR(msg.lParam);
break;
}
}
if (msg.wParam != 0 ¦¦ msg.lParam != 0)
CSocket::AuxQueueAdd(msg.message, msg.wParam, msg.lParam);

bPeek = TRUE;
}
else if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_TIMER, WM_TIMER, PM_REMOVE))
{
break;
}

if (bPeek && ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (OnMessagePending())
{
// allow user-interface updates
pThread->OnIdle(-1);
}
else
{
bPeek = FALSE;
}
}
else
{
// no work to do -- allow CPU to sleep
WaitMessage();
bPeek = TRUE;
}
}
CATCH_ALL(e)
{
TRACE0("Error: caught exception in PumpMessage - continuing.\n");
bPeek = TRUE;
}
END_CATCH_ALL
}

::KillTimer(pState->m_hSocketWindow, nTimerID);

if (!bBlocking)
{
WSASetLastError(WSAEINTR);
return FALSE;
}
m_pbBlocking = NULL;

::PostMessage(pState->m_hSocketWindow,WM_SOCKET_NOTIFY,0,0);

return TRUE;

#endif // _MFC_VER
}


STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This bug has been fixed with the Visual C++ 4.2b patch. For more information on this patch, please see the following articles in the Microsoft Knowledge Base:


ARTICLE-ID: Q156934
TITLE : PATCH: Visual C++ 4.2b Patch

ARTICLE-ID: Q160491
TITLE : Information on Files Modified by VC42b Patch: Part 1 of 4

ARTICLE-ID: Q160496
TITLE : Information on Files Modified by VC42b Patch: Part 2 of 4

ARTICLE-ID: Q160505
TITLE : Information on Files Modified by VC42b Patch: Part 3 of 4

ARTICLE-ID: Q160506
TITLE : Information on Files Modified by VC42b Patch: Part 4 of 4




--------------------------------------------------------------------------------

Additional query words: CAsyncSocket CSocket hangs timer
Keywords : MfcSockets vcbuglist420 vcfixlist420 kbnetwork kbprg kbbuglist kbfixlist
Technology : kbMfc
Version : 4.2
Platform : NT WINDOWS
Issue type : kbbug
Solution Type : kbfix


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.


Last reviewed: September 19, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.




转移贴子到 Visual C++ Visual Basic Delphi C/C++ C++ Builder ASM 数据库开发 PowerBuilder ActiveX/COM 数据算法 软件工程 图形/游戏/多媒体 安全技术 网络/通讯 技术书籍 文件格式 C# XML 数据仓库 主页制作 图形处理 ASP PHP Perl Java Javascript JSP 软件使用 资源使用 软件注册 我看软件 寻找软件 行业软件 软件评测 Windows 95/98 Windows NT/2000 DOS Linux/Unix 硬件指南 程序人生 软件市场 程序员考试 人才热线 建议和意见 灌水乐园 走向海外 程序员杂志 | 贴子加分 | 删除贴子


回复贴子:


--------------------------------------------------------------------------------

我要回复: 有人参与讨论这个问题,请用EMail通知我


返回问题 | 关闭窗口





美达美简介 广告服务 英语步步高 程序员大本营 百联美达美科技有限公司 版权所有




masterlee 2001-05-28
  • 打赏
  • 举报
回复

CSDN首页 | 新闻聚焦 | 共享软件 | 俱乐部 | 开发文档 | 专家门诊 | 招聘求职 | Linux园地 | 程序员杂志
--------------------------------------------------------------------------------

我要回复 | 打印贴子 | 推荐给朋友 | 关闭窗口

主  题:有关MFC中CSocket类超时存在的BUG,讨论!!!
作  者:masterlee
所属论坛:Visual C++
问题点数:20
回复次数:0
人气指数:0
发表时间:2001-5-28 9:41:00

本人在使用CSocket类的过程中发现超时问题很难控制。
在MFC中提到如下:


FIX: CSocket Operation Hangs if a Timer is Active
Last reviewed: September 19, 1997
Article ID: Q154649
The information in this article applies to:
The Microsoft Foundation Classes (MFC) included with: Microsoft Visual C++, 32-bit Edition, version 4.2


SYMPTOMS
A call to CSocket Connect, Accept, Send, or Receive hangs if a timer is active.



CAUSE
CSocket operations are written using "pseudo-blocking." The WinSock API call is not a true blocking call, but if it doesn't return immediately then CSocket will call PumpMessages. PumpMessages looks for the FD_xxx notification and the CSocket function will not return until the FD_xxx notification arrives.

PumpMessages will not detect the socket notification if a timer is active because it looks for WM_TIMER messages first. When a WM_TIMER message arrives, the function doesn't look any further for other messages.

The PumpMessages function is looking for WM_TIMER messages because it sets up its own timer to cause the application to retry its socket calls and do periodic idle-time processing while waiting for the socket notification.



RESOLUTION
There are two possible resolutions:


Disable all timers while making CSocket calls.

Override the PumpMessages function so that it only looks for its own WM_TIMER messages and does not pick up other timer messages. This can be done by borrowing the CSocket::PumpMessages function from SOCKCORE.CPP and changing it as follows:
#if _MFC_VER == 0x0420


#define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE
#define WM_SOCKET_NOTIFY 0x0373
#define WM_SOCKET_DEAD 0x0374

#define _afxSockThreadState AfxGetModuleThreadState()

#endif

BOOL CMySocket::PumpMessages(UINT uStopFlag)
{
#if _MFC_VER != 0x0420
return CSocket::PumpMessages(uStopFlag);
#else

// The same socket better not be blocking in more than one place.
ASSERT(m_pbBlocking == NULL);

_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;

ASSERT(pState->m_hSocketWindow != NULL);

BOOL bBlocking = TRUE;
m_pbBlocking = &bBlocking;
CWinThread* pThread = AfxGetThread();

// This is not a timeout in the WinSock sense, but more
// like a WM_KICKIDLE to keep message pumping alive
UINT nTimerID = ::SetTimer(pState->m_hSocketWindow, 0,
m_nTimeOut, NULL);

if (nTimerID == 0)
AfxThrowResourceException();

BOOL bPeek = TRUE;

while (bBlocking)
{
TRY
{
MSG msg;
if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_SOCKET_NOTIFY, WM_SOCKET_DEAD, PM_REMOVE))
{
if (msg.message == WM_SOCKET_NOTIFY &&
(SOCKET)msg.wParam == m_hSocket)
{
if (WSAGETSELECTEVENT(msg.lParam) == FD_CLOSE)
{
break;
}
if (WSAGETSELECTEVENT(msg.lParam) == uStopFlag)
{
if (uStopFlag == FD_CONNECT)
m_nConnectError = WSAGETSELECTERROR(msg.lParam);
break;
}
}
if (msg.wParam != 0 ¦¦ msg.lParam != 0)
CSocket::AuxQueueAdd(msg.message, msg.wParam, msg.lParam);

bPeek = TRUE;
}
else if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_TIMER, WM_TIMER, PM_REMOVE))
{
break;
}

if (bPeek && ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (OnMessagePending())
{
// allow user-interface updates
pThread->OnIdle(-1);
}
else
{
bPeek = FALSE;
}
}
else
{
// no work to do -- allow CPU to sleep
WaitMessage();
bPeek = TRUE;
}
}
CATCH_ALL(e)
{
TRACE0("Error: caught exception in PumpMessage - continuing.\n");
bPeek = TRUE;
}
END_CATCH_ALL
}

::KillTimer(pState->m_hSocketWindow, nTimerID);

if (!bBlocking)
{
WSASetLastError(WSAEINTR);
return FALSE;
}
m_pbBlocking = NULL;

::PostMessage(pState->m_hSocketWindow,WM_SOCKET_NOTIFY,0,0);

return TRUE;

#endif // _MFC_VER
}


STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This bug has been fixed with the Visual C++ 4.2b patch. For more information on this patch, please see the following articles in the Microsoft Knowledge Base:


ARTICLE-ID: Q156934
TITLE : PATCH: Visual C++ 4.2b Patch

ARTICLE-ID: Q160491
TITLE : Information on Files Modified by VC42b Patch: Part 1 of 4

ARTICLE-ID: Q160496
TITLE : Information on Files Modified by VC42b Patch: Part 2 of 4

ARTICLE-ID: Q160505
TITLE : Information on Files Modified by VC42b Patch: Part 3 of 4

ARTICLE-ID: Q160506
TITLE : Information on Files Modified by VC42b Patch: Part 4 of 4




--------------------------------------------------------------------------------

Additional query words: CAsyncSocket CSocket hangs timer
Keywords : MfcSockets vcbuglist420 vcfixlist420 kbnetwork kbprg kbbuglist kbfixlist
Technology : kbMfc
Version : 4.2
Platform : NT WINDOWS
Issue type : kbbug
Solution Type : kbfix


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.


Last reviewed: September 19, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.




转移贴子到 Visual C++ Visual Basic Delphi C/C++ C++ Builder ASM 数据库开发 PowerBuilder ActiveX/COM 数据算法 软件工程 图形/游戏/多媒体 安全技术 网络/通讯 技术书籍 文件格式 C# XML 数据仓库 主页制作 图形处理 ASP PHP Perl Java Javascript JSP 软件使用 资源使用 软件注册 我看软件 寻找软件 行业软件 软件评测 Windows 95/98 Windows NT/2000 DOS Linux/Unix 硬件指南 程序人生 软件市场 程序员考试 人才热线 建议和意见 灌水乐园 走向海外 程序员杂志 | 贴子加分 | 删除贴子


回复贴子:


--------------------------------------------------------------------------------

我要回复: 有人参与讨论这个问题,请用EMail通知我


返回问题 | 关闭窗口





美达美简介 广告服务 英语步步高 程序员大本营 百联美达美科技有限公司 版权所有




masterlee 2001-05-28
  • 打赏
  • 举报
回复

CSDN首页 | 新闻聚焦 | 共享软件 | 俱乐部 | 开发文档 | 专家门诊 | 招聘求职 | Linux园地 | 程序员杂志
--------------------------------------------------------------------------------

我要回复 | 打印贴子 | 推荐给朋友 | 关闭窗口

主  题:有关MFC中CSocket类超时存在的BUG,讨论!!!
作  者:masterlee
所属论坛:Visual C++
问题点数:20
回复次数:0
人气指数:0
发表时间:2001-5-28 9:41:00

本人在使用CSocket类的过程中发现超时问题很难控制。
在MFC中提到如下:


FIX: CSocket Operation Hangs if a Timer is Active
Last reviewed: September 19, 1997
Article ID: Q154649
The information in this article applies to:
The Microsoft Foundation Classes (MFC) included with: Microsoft Visual C++, 32-bit Edition, version 4.2


SYMPTOMS
A call to CSocket Connect, Accept, Send, or Receive hangs if a timer is active.



CAUSE
CSocket operations are written using "pseudo-blocking." The WinSock API call is not a true blocking call, but if it doesn't return immediately then CSocket will call PumpMessages. PumpMessages looks for the FD_xxx notification and the CSocket function will not return until the FD_xxx notification arrives.

PumpMessages will not detect the socket notification if a timer is active because it looks for WM_TIMER messages first. When a WM_TIMER message arrives, the function doesn't look any further for other messages.

The PumpMessages function is looking for WM_TIMER messages because it sets up its own timer to cause the application to retry its socket calls and do periodic idle-time processing while waiting for the socket notification.



RESOLUTION
There are two possible resolutions:


Disable all timers while making CSocket calls.

Override the PumpMessages function so that it only looks for its own WM_TIMER messages and does not pick up other timer messages. This can be done by borrowing the CSocket::PumpMessages function from SOCKCORE.CPP and changing it as follows:
#if _MFC_VER == 0x0420


#define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE
#define WM_SOCKET_NOTIFY 0x0373
#define WM_SOCKET_DEAD 0x0374

#define _afxSockThreadState AfxGetModuleThreadState()

#endif

BOOL CMySocket::PumpMessages(UINT uStopFlag)
{
#if _MFC_VER != 0x0420
return CSocket::PumpMessages(uStopFlag);
#else

// The same socket better not be blocking in more than one place.
ASSERT(m_pbBlocking == NULL);

_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;

ASSERT(pState->m_hSocketWindow != NULL);

BOOL bBlocking = TRUE;
m_pbBlocking = &bBlocking;
CWinThread* pThread = AfxGetThread();

// This is not a timeout in the WinSock sense, but more
// like a WM_KICKIDLE to keep message pumping alive
UINT nTimerID = ::SetTimer(pState->m_hSocketWindow, 0,
m_nTimeOut, NULL);

if (nTimerID == 0)
AfxThrowResourceException();

BOOL bPeek = TRUE;

while (bBlocking)
{
TRY
{
MSG msg;
if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_SOCKET_NOTIFY, WM_SOCKET_DEAD, PM_REMOVE))
{
if (msg.message == WM_SOCKET_NOTIFY &&
(SOCKET)msg.wParam == m_hSocket)
{
if (WSAGETSELECTEVENT(msg.lParam) == FD_CLOSE)
{
break;
}
if (WSAGETSELECTEVENT(msg.lParam) == uStopFlag)
{
if (uStopFlag == FD_CONNECT)
m_nConnectError = WSAGETSELECTERROR(msg.lParam);
break;
}
}
if (msg.wParam != 0 ¦¦ msg.lParam != 0)
CSocket::AuxQueueAdd(msg.message, msg.wParam, msg.lParam);

bPeek = TRUE;
}
else if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_TIMER, WM_TIMER, PM_REMOVE))
{
break;
}

if (bPeek && ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (OnMessagePending())
{
// allow user-interface updates
pThread->OnIdle(-1);
}
else
{
bPeek = FALSE;
}
}
else
{
// no work to do -- allow CPU to sleep
WaitMessage();
bPeek = TRUE;
}
}
CATCH_ALL(e)
{
TRACE0("Error: caught exception in PumpMessage - continuing.\n");
bPeek = TRUE;
}
END_CATCH_ALL
}

::KillTimer(pState->m_hSocketWindow, nTimerID);

if (!bBlocking)
{
WSASetLastError(WSAEINTR);
return FALSE;
}
m_pbBlocking = NULL;

::PostMessage(pState->m_hSocketWindow,WM_SOCKET_NOTIFY,0,0);

return TRUE;

#endif // _MFC_VER
}


STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This bug has been fixed with the Visual C++ 4.2b patch. For more information on this patch, please see the following articles in the Microsoft Knowledge Base:


ARTICLE-ID: Q156934
TITLE : PATCH: Visual C++ 4.2b Patch

ARTICLE-ID: Q160491
TITLE : Information on Files Modified by VC42b Patch: Part 1 of 4

ARTICLE-ID: Q160496
TITLE : Information on Files Modified by VC42b Patch: Part 2 of 4

ARTICLE-ID: Q160505
TITLE : Information on Files Modified by VC42b Patch: Part 3 of 4

ARTICLE-ID: Q160506
TITLE : Information on Files Modified by VC42b Patch: Part 4 of 4




--------------------------------------------------------------------------------

Additional query words: CAsyncSocket CSocket hangs timer
Keywords : MfcSockets vcbuglist420 vcfixlist420 kbnetwork kbprg kbbuglist kbfixlist
Technology : kbMfc
Version : 4.2
Platform : NT WINDOWS
Issue type : kbbug
Solution Type : kbfix


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.


Last reviewed: September 19, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.




转移贴子到 Visual C++ Visual Basic Delphi C/C++ C++ Builder ASM 数据库开发 PowerBuilder ActiveX/COM 数据算法 软件工程 图形/游戏/多媒体 安全技术 网络/通讯 技术书籍 文件格式 C# XML 数据仓库 主页制作 图形处理 ASP PHP Perl Java Javascript JSP 软件使用 资源使用 软件注册 我看软件 寻找软件 行业软件 软件评测 Windows 95/98 Windows NT/2000 DOS Linux/Unix 硬件指南 程序人生 软件市场 程序员考试 人才热线 建议和意见 灌水乐园 走向海外 程序员杂志 | 贴子加分 | 删除贴子


回复贴子:


--------------------------------------------------------------------------------

我要回复: 有人参与讨论这个问题,请用EMail通知我


返回问题 | 关闭窗口





美达美简介 广告服务 英语步步高 程序员大本营 百联美达美科技有限公司 版权所有




masterlee 2001-05-28
  • 打赏
  • 举报
回复

CSDN首页 | 新闻聚焦 | 共享软件 | 俱乐部 | 开发文档 | 专家门诊 | 招聘求职 | Linux园地 | 程序员杂志
--------------------------------------------------------------------------------

我要回复 | 打印贴子 | 推荐给朋友 | 关闭窗口

主  题:有关MFC中CSocket类超时存在的BUG,讨论!!!
作  者:masterlee
所属论坛:Visual C++
问题点数:20
回复次数:0
人气指数:0
发表时间:2001-5-28 9:41:00

本人在使用CSocket类的过程中发现超时问题很难控制。
在MFC中提到如下:


FIX: CSocket Operation Hangs if a Timer is Active
Last reviewed: September 19, 1997
Article ID: Q154649
The information in this article applies to:
The Microsoft Foundation Classes (MFC) included with: Microsoft Visual C++, 32-bit Edition, version 4.2


SYMPTOMS
A call to CSocket Connect, Accept, Send, or Receive hangs if a timer is active.



CAUSE
CSocket operations are written using "pseudo-blocking." The WinSock API call is not a true blocking call, but if it doesn't return immediately then CSocket will call PumpMessages. PumpMessages looks for the FD_xxx notification and the CSocket function will not return until the FD_xxx notification arrives.

PumpMessages will not detect the socket notification if a timer is active because it looks for WM_TIMER messages first. When a WM_TIMER message arrives, the function doesn't look any further for other messages.

The PumpMessages function is looking for WM_TIMER messages because it sets up its own timer to cause the application to retry its socket calls and do periodic idle-time processing while waiting for the socket notification.



RESOLUTION
There are two possible resolutions:


Disable all timers while making CSocket calls.

Override the PumpMessages function so that it only looks for its own WM_TIMER messages and does not pick up other timer messages. This can be done by borrowing the CSocket::PumpMessages function from SOCKCORE.CPP and changing it as follows:
#if _MFC_VER == 0x0420


#define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE
#define WM_SOCKET_NOTIFY 0x0373
#define WM_SOCKET_DEAD 0x0374

#define _afxSockThreadState AfxGetModuleThreadState()

#endif

BOOL CMySocket::PumpMessages(UINT uStopFlag)
{
#if _MFC_VER != 0x0420
return CSocket::PumpMessages(uStopFlag);
#else

// The same socket better not be blocking in more than one place.
ASSERT(m_pbBlocking == NULL);

_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;

ASSERT(pState->m_hSocketWindow != NULL);

BOOL bBlocking = TRUE;
m_pbBlocking = &bBlocking;
CWinThread* pThread = AfxGetThread();

// This is not a timeout in the WinSock sense, but more
// like a WM_KICKIDLE to keep message pumping alive
UINT nTimerID = ::SetTimer(pState->m_hSocketWindow, 0,
m_nTimeOut, NULL);

if (nTimerID == 0)
AfxThrowResourceException();

BOOL bPeek = TRUE;

while (bBlocking)
{
TRY
{
MSG msg;
if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_SOCKET_NOTIFY, WM_SOCKET_DEAD, PM_REMOVE))
{
if (msg.message == WM_SOCKET_NOTIFY &&
(SOCKET)msg.wParam == m_hSocket)
{
if (WSAGETSELECTEVENT(msg.lParam) == FD_CLOSE)
{
break;
}
if (WSAGETSELECTEVENT(msg.lParam) == uStopFlag)
{
if (uStopFlag == FD_CONNECT)
m_nConnectError = WSAGETSELECTERROR(msg.lParam);
break;
}
}
if (msg.wParam != 0 ¦¦ msg.lParam != 0)
CSocket::AuxQueueAdd(msg.message, msg.wParam, msg.lParam);

bPeek = TRUE;
}
else if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_TIMER, WM_TIMER, PM_REMOVE))
{
break;
}

if (bPeek && ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (OnMessagePending())
{
// allow user-interface updates
pThread->OnIdle(-1);
}
else
{
bPeek = FALSE;
}
}
else
{
// no work to do -- allow CPU to sleep
WaitMessage();
bPeek = TRUE;
}
}
CATCH_ALL(e)
{
TRACE0("Error: caught exception in PumpMessage - continuing.\n");
bPeek = TRUE;
}
END_CATCH_ALL
}

::KillTimer(pState->m_hSocketWindow, nTimerID);

if (!bBlocking)
{
WSASetLastError(WSAEINTR);
return FALSE;
}
m_pbBlocking = NULL;

::PostMessage(pState->m_hSocketWindow,WM_SOCKET_NOTIFY,0,0);

return TRUE;

#endif // _MFC_VER
}


STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This bug has been fixed with the Visual C++ 4.2b patch. For more information on this patch, please see the following articles in the Microsoft Knowledge Base:


ARTICLE-ID: Q156934
TITLE : PATCH: Visual C++ 4.2b Patch

ARTICLE-ID: Q160491
TITLE : Information on Files Modified by VC42b Patch: Part 1 of 4

ARTICLE-ID: Q160496
TITLE : Information on Files Modified by VC42b Patch: Part 2 of 4

ARTICLE-ID: Q160505
TITLE : Information on Files Modified by VC42b Patch: Part 3 of 4

ARTICLE-ID: Q160506
TITLE : Information on Files Modified by VC42b Patch: Part 4 of 4




--------------------------------------------------------------------------------

Additional query words: CAsyncSocket CSocket hangs timer
Keywords : MfcSockets vcbuglist420 vcfixlist420 kbnetwork kbprg kbbuglist kbfixlist
Technology : kbMfc
Version : 4.2
Platform : NT WINDOWS
Issue type : kbbug
Solution Type : kbfix


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.


Last reviewed: September 19, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.




转移贴子到 Visual C++ Visual Basic Delphi C/C++ C++ Builder ASM 数据库开发 PowerBuilder ActiveX/COM 数据算法 软件工程 图形/游戏/多媒体 安全技术 网络/通讯 技术书籍 文件格式 C# XML 数据仓库 主页制作 图形处理 ASP PHP Perl Java Javascript JSP 软件使用 资源使用 软件注册 我看软件 寻找软件 行业软件 软件评测 Windows 95/98 Windows NT/2000 DOS Linux/Unix 硬件指南 程序人生 软件市场 程序员考试 人才热线 建议和意见 灌水乐园 走向海外 程序员杂志 | 贴子加分 | 删除贴子


回复贴子:


--------------------------------------------------------------------------------

我要回复: 有人参与讨论这个问题,请用EMail通知我


返回问题 | 关闭窗口





美达美简介 广告服务 英语步步高 程序员大本营 百联美达美科技有限公司 版权所有




masterlee 2001-05-28
  • 打赏
  • 举报
回复

CSDN首页 | 新闻聚焦 | 共享软件 | 俱乐部 | 开发文档 | 专家门诊 | 招聘求职 | Linux园地 | 程序员杂志
--------------------------------------------------------------------------------

我要回复 | 打印贴子 | 推荐给朋友 | 关闭窗口

主  题:有关MFC中CSocket类超时存在的BUG,讨论!!!
作  者:masterlee
所属论坛:Visual C++
问题点数:20
回复次数:0
人气指数:0
发表时间:2001-5-28 9:41:00

本人在使用CSocket类的过程中发现超时问题很难控制。
在MFC中提到如下:


FIX: CSocket Operation Hangs if a Timer is Active
Last reviewed: September 19, 1997
Article ID: Q154649
The information in this article applies to:
The Microsoft Foundation Classes (MFC) included with: Microsoft Visual C++, 32-bit Edition, version 4.2


SYMPTOMS
A call to CSocket Connect, Accept, Send, or Receive hangs if a timer is active.



CAUSE
CSocket operations are written using "pseudo-blocking." The WinSock API call is not a true blocking call, but if it doesn't return immediately then CSocket will call PumpMessages. PumpMessages looks for the FD_xxx notification and the CSocket function will not return until the FD_xxx notification arrives.

PumpMessages will not detect the socket notification if a timer is active because it looks for WM_TIMER messages first. When a WM_TIMER message arrives, the function doesn't look any further for other messages.

The PumpMessages function is looking for WM_TIMER messages because it sets up its own timer to cause the application to retry its socket calls and do periodic idle-time processing while waiting for the socket notification.



RESOLUTION
There are two possible resolutions:


Disable all timers while making CSocket calls.

Override the PumpMessages function so that it only looks for its own WM_TIMER messages and does not pick up other timer messages. This can be done by borrowing the CSocket::PumpMessages function from SOCKCORE.CPP and changing it as follows:
#if _MFC_VER == 0x0420


#define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE
#define WM_SOCKET_NOTIFY 0x0373
#define WM_SOCKET_DEAD 0x0374

#define _afxSockThreadState AfxGetModuleThreadState()

#endif

BOOL CMySocket::PumpMessages(UINT uStopFlag)
{
#if _MFC_VER != 0x0420
return CSocket::PumpMessages(uStopFlag);
#else

// The same socket better not be blocking in more than one place.
ASSERT(m_pbBlocking == NULL);

_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;

ASSERT(pState->m_hSocketWindow != NULL);

BOOL bBlocking = TRUE;
m_pbBlocking = &bBlocking;
CWinThread* pThread = AfxGetThread();

// This is not a timeout in the WinSock sense, but more
// like a WM_KICKIDLE to keep message pumping alive
UINT nTimerID = ::SetTimer(pState->m_hSocketWindow, 0,
m_nTimeOut, NULL);

if (nTimerID == 0)
AfxThrowResourceException();

BOOL bPeek = TRUE;

while (bBlocking)
{
TRY
{
MSG msg;
if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_SOCKET_NOTIFY, WM_SOCKET_DEAD, PM_REMOVE))
{
if (msg.message == WM_SOCKET_NOTIFY &&
(SOCKET)msg.wParam == m_hSocket)
{
if (WSAGETSELECTEVENT(msg.lParam) == FD_CLOSE)
{
break;
}
if (WSAGETSELECTEVENT(msg.lParam) == uStopFlag)
{
if (uStopFlag == FD_CONNECT)
m_nConnectError = WSAGETSELECTERROR(msg.lParam);
break;
}
}
if (msg.wParam != 0 ¦¦ msg.lParam != 0)
CSocket::AuxQueueAdd(msg.message, msg.wParam, msg.lParam);

bPeek = TRUE;
}
else if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_TIMER, WM_TIMER, PM_REMOVE))
{
break;
}

if (bPeek && ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (OnMessagePending())
{
// allow user-interface updates
pThread->OnIdle(-1);
}
else
{
bPeek = FALSE;
}
}
else
{
// no work to do -- allow CPU to sleep
WaitMessage();
bPeek = TRUE;
}
}
CATCH_ALL(e)
{
TRACE0("Error: caught exception in PumpMessage - continuing.\n");
bPeek = TRUE;
}
END_CATCH_ALL
}

::KillTimer(pState->m_hSocketWindow, nTimerID);

if (!bBlocking)
{
WSASetLastError(WSAEINTR);
return FALSE;
}
m_pbBlocking = NULL;

::PostMessage(pState->m_hSocketWindow,WM_SOCKET_NOTIFY,0,0);

return TRUE;

#endif // _MFC_VER
}


STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This bug has been fixed with the Visual C++ 4.2b patch. For more information on this patch, please see the following articles in the Microsoft Knowledge Base:


ARTICLE-ID: Q156934
TITLE : PATCH: Visual C++ 4.2b Patch

ARTICLE-ID: Q160491
TITLE : Information on Files Modified by VC42b Patch: Part 1 of 4

ARTICLE-ID: Q160496
TITLE : Information on Files Modified by VC42b Patch: Part 2 of 4

ARTICLE-ID: Q160505
TITLE : Information on Files Modified by VC42b Patch: Part 3 of 4

ARTICLE-ID: Q160506
TITLE : Information on Files Modified by VC42b Patch: Part 4 of 4




--------------------------------------------------------------------------------

Additional query words: CAsyncSocket CSocket hangs timer
Keywords : MfcSockets vcbuglist420 vcfixlist420 kbnetwork kbprg kbbuglist kbfixlist
Technology : kbMfc
Version : 4.2
Platform : NT WINDOWS
Issue type : kbbug
Solution Type : kbfix


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.


Last reviewed: September 19, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.




转移贴子到 Visual C++ Visual Basic Delphi C/C++ C++ Builder ASM 数据库开发 PowerBuilder ActiveX/COM 数据算法 软件工程 图形/游戏/多媒体 安全技术 网络/通讯 技术书籍 文件格式 C# XML 数据仓库 主页制作 图形处理 ASP PHP Perl Java Javascript JSP 软件使用 资源使用 软件注册 我看软件 寻找软件 行业软件 软件评测 Windows 95/98 Windows NT/2000 DOS Linux/Unix 硬件指南 程序人生 软件市场 程序员考试 人才热线 建议和意见 灌水乐园 走向海外 程序员杂志 | 贴子加分 | 删除贴子


回复贴子:


--------------------------------------------------------------------------------

我要回复: 有人参与讨论这个问题,请用EMail通知我


返回问题 | 关闭窗口





美达美简介 广告服务 英语步步高 程序员大本营 百联美达美科技有限公司 版权所有




masterlee 2001-05-28
  • 打赏
  • 举报
回复

CSDN首页 | 新闻聚焦 | 共享软件 | 俱乐部 | 开发文档 | 专家门诊 | 招聘求职 | Linux园地 | 程序员杂志
--------------------------------------------------------------------------------

我要回复 | 打印贴子 | 推荐给朋友 | 关闭窗口

主  题:有关MFC中CSocket类超时存在的BUG,讨论!!!
作  者:masterlee
所属论坛:Visual C++
问题点数:20
回复次数:0
人气指数:0
发表时间:2001-5-28 9:41:00

本人在使用CSocket类的过程中发现超时问题很难控制。
在MFC中提到如下:


FIX: CSocket Operation Hangs if a Timer is Active
Last reviewed: September 19, 1997
Article ID: Q154649
The information in this article applies to:
The Microsoft Foundation Classes (MFC) included with: Microsoft Visual C++, 32-bit Edition, version 4.2


SYMPTOMS
A call to CSocket Connect, Accept, Send, or Receive hangs if a timer is active.



CAUSE
CSocket operations are written using "pseudo-blocking." The WinSock API call is not a true blocking call, but if it doesn't return immediately then CSocket will call PumpMessages. PumpMessages looks for the FD_xxx notification and the CSocket function will not return until the FD_xxx notification arrives.

PumpMessages will not detect the socket notification if a timer is active because it looks for WM_TIMER messages first. When a WM_TIMER message arrives, the function doesn't look any further for other messages.

The PumpMessages function is looking for WM_TIMER messages because it sets up its own timer to cause the application to retry its socket calls and do periodic idle-time processing while waiting for the socket notification.



RESOLUTION
There are two possible resolutions:


Disable all timers while making CSocket calls.

Override the PumpMessages function so that it only looks for its own WM_TIMER messages and does not pick up other timer messages. This can be done by borrowing the CSocket::PumpMessages function from SOCKCORE.CPP and changing it as follows:
#if _MFC_VER == 0x0420


#define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE
#define WM_SOCKET_NOTIFY 0x0373
#define WM_SOCKET_DEAD 0x0374

#define _afxSockThreadState AfxGetModuleThreadState()

#endif

BOOL CMySocket::PumpMessages(UINT uStopFlag)
{
#if _MFC_VER != 0x0420
return CSocket::PumpMessages(uStopFlag);
#else

// The same socket better not be blocking in more than one place.
ASSERT(m_pbBlocking == NULL);

_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;

ASSERT(pState->m_hSocketWindow != NULL);

BOOL bBlocking = TRUE;
m_pbBlocking = &bBlocking;
CWinThread* pThread = AfxGetThread();

// This is not a timeout in the WinSock sense, but more
// like a WM_KICKIDLE to keep message pumping alive
UINT nTimerID = ::SetTimer(pState->m_hSocketWindow, 0,
m_nTimeOut, NULL);

if (nTimerID == 0)
AfxThrowResourceException();

BOOL bPeek = TRUE;

while (bBlocking)
{
TRY
{
MSG msg;
if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_SOCKET_NOTIFY, WM_SOCKET_DEAD, PM_REMOVE))
{
if (msg.message == WM_SOCKET_NOTIFY &&
(SOCKET)msg.wParam == m_hSocket)
{
if (WSAGETSELECTEVENT(msg.lParam) == FD_CLOSE)
{
break;
}
if (WSAGETSELECTEVENT(msg.lParam) == uStopFlag)
{
if (uStopFlag == FD_CONNECT)
m_nConnectError = WSAGETSELECTERROR(msg.lParam);
break;
}
}
if (msg.wParam != 0 ¦¦ msg.lParam != 0)
CSocket::AuxQueueAdd(msg.message, msg.wParam, msg.lParam);

bPeek = TRUE;
}
else if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_TIMER, WM_TIMER, PM_REMOVE))
{
break;
}

if (bPeek && ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (OnMessagePending())
{
// allow user-interface updates
pThread->OnIdle(-1);
}
else
{
bPeek = FALSE;
}
}
else
{
// no work to do -- allow CPU to sleep
WaitMessage();
bPeek = TRUE;
}
}
CATCH_ALL(e)
{
TRACE0("Error: caught exception in PumpMessage - continuing.\n");
bPeek = TRUE;
}
END_CATCH_ALL
}

::KillTimer(pState->m_hSocketWindow, nTimerID);

if (!bBlocking)
{
WSASetLastError(WSAEINTR);
return FALSE;
}
m_pbBlocking = NULL;

::PostMessage(pState->m_hSocketWindow,WM_SOCKET_NOTIFY,0,0);

return TRUE;

#endif // _MFC_VER
}


STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This bug has been fixed with the Visual C++ 4.2b patch. For more information on this patch, please see the following articles in the Microsoft Knowledge Base:


ARTICLE-ID: Q156934
TITLE : PATCH: Visual C++ 4.2b Patch

ARTICLE-ID: Q160491
TITLE : Information on Files Modified by VC42b Patch: Part 1 of 4

ARTICLE-ID: Q160496
TITLE : Information on Files Modified by VC42b Patch: Part 2 of 4

ARTICLE-ID: Q160505
TITLE : Information on Files Modified by VC42b Patch: Part 3 of 4

ARTICLE-ID: Q160506
TITLE : Information on Files Modified by VC42b Patch: Part 4 of 4




--------------------------------------------------------------------------------

Additional query words: CAsyncSocket CSocket hangs timer
Keywords : MfcSockets vcbuglist420 vcfixlist420 kbnetwork kbprg kbbuglist kbfixlist
Technology : kbMfc
Version : 4.2
Platform : NT WINDOWS
Issue type : kbbug
Solution Type : kbfix


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.


Last reviewed: September 19, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.




转移贴子到 Visual C++ Visual Basic Delphi C/C++ C++ Builder ASM 数据库开发 PowerBuilder ActiveX/COM 数据算法 软件工程 图形/游戏/多媒体 安全技术 网络/通讯 技术书籍 文件格式 C# XML 数据仓库 主页制作 图形处理 ASP PHP Perl Java Javascript JSP 软件使用 资源使用 软件注册 我看软件 寻找软件 行业软件 软件评测 Windows 95/98 Windows NT/2000 DOS Linux/Unix 硬件指南 程序人生 软件市场 程序员考试 人才热线 建议和意见 灌水乐园 走向海外 程序员杂志 | 贴子加分 | 删除贴子


回复贴子:


--------------------------------------------------------------------------------

我要回复: 有人参与讨论这个问题,请用EMail通知我


返回问题 | 关闭窗口





美达美简介 广告服务 英语步步高 程序员大本营 百联美达美科技有限公司 版权所有




masterlee 2001-05-28
  • 打赏
  • 举报
回复

CSDN首页 | 新闻聚焦 | 共享软件 | 俱乐部 | 开发文档 | 专家门诊 | 招聘求职 | Linux园地 | 程序员杂志
--------------------------------------------------------------------------------

我要回复 | 打印贴子 | 推荐给朋友 | 关闭窗口

主  题:有关MFC中CSocket类超时存在的BUG,讨论!!!
作  者:masterlee
所属论坛:Visual C++
问题点数:20
回复次数:0
人气指数:0
发表时间:2001-5-28 9:41:00

本人在使用CSocket类的过程中发现超时问题很难控制。
在MFC中提到如下:


FIX: CSocket Operation Hangs if a Timer is Active
Last reviewed: September 19, 1997
Article ID: Q154649
The information in this article applies to:
The Microsoft Foundation Classes (MFC) included with: Microsoft Visual C++, 32-bit Edition, version 4.2


SYMPTOMS
A call to CSocket Connect, Accept, Send, or Receive hangs if a timer is active.



CAUSE
CSocket operations are written using "pseudo-blocking." The WinSock API call is not a true blocking call, but if it doesn't return immediately then CSocket will call PumpMessages. PumpMessages looks for the FD_xxx notification and the CSocket function will not return until the FD_xxx notification arrives.

PumpMessages will not detect the socket notification if a timer is active because it looks for WM_TIMER messages first. When a WM_TIMER message arrives, the function doesn't look any further for other messages.

The PumpMessages function is looking for WM_TIMER messages because it sets up its own timer to cause the application to retry its socket calls and do periodic idle-time processing while waiting for the socket notification.



RESOLUTION
There are two possible resolutions:


Disable all timers while making CSocket calls.

Override the PumpMessages function so that it only looks for its own WM_TIMER messages and does not pick up other timer messages. This can be done by borrowing the CSocket::PumpMessages function from SOCKCORE.CPP and changing it as follows:
#if _MFC_VER == 0x0420


#define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE
#define WM_SOCKET_NOTIFY 0x0373
#define WM_SOCKET_DEAD 0x0374

#define _afxSockThreadState AfxGetModuleThreadState()

#endif

BOOL CMySocket::PumpMessages(UINT uStopFlag)
{
#if _MFC_VER != 0x0420
return CSocket::PumpMessages(uStopFlag);
#else

// The same socket better not be blocking in more than one place.
ASSERT(m_pbBlocking == NULL);

_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;

ASSERT(pState->m_hSocketWindow != NULL);

BOOL bBlocking = TRUE;
m_pbBlocking = &bBlocking;
CWinThread* pThread = AfxGetThread();

// This is not a timeout in the WinSock sense, but more
// like a WM_KICKIDLE to keep message pumping alive
UINT nTimerID = ::SetTimer(pState->m_hSocketWindow, 0,
m_nTimeOut, NULL);

if (nTimerID == 0)
AfxThrowResourceException();

BOOL bPeek = TRUE;

while (bBlocking)
{
TRY
{
MSG msg;
if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_SOCKET_NOTIFY, WM_SOCKET_DEAD, PM_REMOVE))
{
if (msg.message == WM_SOCKET_NOTIFY &&
(SOCKET)msg.wParam == m_hSocket)
{
if (WSAGETSELECTEVENT(msg.lParam) == FD_CLOSE)
{
break;
}
if (WSAGETSELECTEVENT(msg.lParam) == uStopFlag)
{
if (uStopFlag == FD_CONNECT)
m_nConnectError = WSAGETSELECTERROR(msg.lParam);
break;
}
}
if (msg.wParam != 0 ¦¦ msg.lParam != 0)
CSocket::AuxQueueAdd(msg.message, msg.wParam, msg.lParam);

bPeek = TRUE;
}
else if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_TIMER, WM_TIMER, PM_REMOVE))
{
break;
}

if (bPeek && ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (OnMessagePending())
{
// allow user-interface updates
pThread->OnIdle(-1);
}
else
{
bPeek = FALSE;
}
}
else
{
// no work to do -- allow CPU to sleep
WaitMessage();
bPeek = TRUE;
}
}
CATCH_ALL(e)
{
TRACE0("Error: caught exception in PumpMessage - continuing.\n");
bPeek = TRUE;
}
END_CATCH_ALL
}

::KillTimer(pState->m_hSocketWindow, nTimerID);

if (!bBlocking)
{
WSASetLastError(WSAEINTR);
return FALSE;
}
m_pbBlocking = NULL;

::PostMessage(pState->m_hSocketWindow,WM_SOCKET_NOTIFY,0,0);

return TRUE;

#endif // _MFC_VER
}


STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This bug has been fixed with the Visual C++ 4.2b patch. For more information on this patch, please see the following articles in the Microsoft Knowledge Base:


ARTICLE-ID: Q156934
TITLE : PATCH: Visual C++ 4.2b Patch

ARTICLE-ID: Q160491
TITLE : Information on Files Modified by VC42b Patch: Part 1 of 4

ARTICLE-ID: Q160496
TITLE : Information on Files Modified by VC42b Patch: Part 2 of 4

ARTICLE-ID: Q160505
TITLE : Information on Files Modified by VC42b Patch: Part 3 of 4

ARTICLE-ID: Q160506
TITLE : Information on Files Modified by VC42b Patch: Part 4 of 4




--------------------------------------------------------------------------------

Additional query words: CAsyncSocket CSocket hangs timer
Keywords : MfcSockets vcbuglist420 vcfixlist420 kbnetwork kbprg kbbuglist kbfixlist
Technology : kbMfc
Version : 4.2
Platform : NT WINDOWS
Issue type : kbbug
Solution Type : kbfix


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.


Last reviewed: September 19, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.




转移贴子到 Visual C++ Visual Basic Delphi C/C++ C++ Builder ASM 数据库开发 PowerBuilder ActiveX/COM 数据算法 软件工程 图形/游戏/多媒体 安全技术 网络/通讯 技术书籍 文件格式 C# XML 数据仓库 主页制作 图形处理 ASP PHP Perl Java Javascript JSP 软件使用 资源使用 软件注册 我看软件 寻找软件 行业软件 软件评测 Windows 95/98 Windows NT/2000 DOS Linux/Unix 硬件指南 程序人生 软件市场 程序员考试 人才热线 建议和意见 灌水乐园 走向海外 程序员杂志 | 贴子加分 | 删除贴子


回复贴子:


--------------------------------------------------------------------------------

我要回复: 有人参与讨论这个问题,请用EMail通知我


返回问题 | 关闭窗口





美达美简介 广告服务 英语步步高 程序员大本营 百联美达美科技有限公司 版权所有




masterlee 2001-05-28
  • 打赏
  • 举报
回复

CSDN首页 | 新闻聚焦 | 共享软件 | 俱乐部 | 开发文档 | 专家门诊 | 招聘求职 | Linux园地 | 程序员杂志
--------------------------------------------------------------------------------

我要回复 | 打印贴子 | 推荐给朋友 | 关闭窗口

主  题:有关MFC中CSocket类超时存在的BUG,讨论!!!
作  者:masterlee
所属论坛:Visual C++
问题点数:20
回复次数:0
人气指数:0
发表时间:2001-5-28 9:41:00

本人在使用CSocket类的过程中发现超时问题很难控制。
在MFC中提到如下:


FIX: CSocket Operation Hangs if a Timer is Active
Last reviewed: September 19, 1997
Article ID: Q154649
The information in this article applies to:
The Microsoft Foundation Classes (MFC) included with: Microsoft Visual C++, 32-bit Edition, version 4.2


SYMPTOMS
A call to CSocket Connect, Accept, Send, or Receive hangs if a timer is active.



CAUSE
CSocket operations are written using "pseudo-blocking." The WinSock API call is not a true blocking call, but if it doesn't return immediately then CSocket will call PumpMessages. PumpMessages looks for the FD_xxx notification and the CSocket function will not return until the FD_xxx notification arrives.

PumpMessages will not detect the socket notification if a timer is active because it looks for WM_TIMER messages first. When a WM_TIMER message arrives, the function doesn't look any further for other messages.

The PumpMessages function is looking for WM_TIMER messages because it sets up its own timer to cause the application to retry its socket calls and do periodic idle-time processing while waiting for the socket notification.



RESOLUTION
There are two possible resolutions:


Disable all timers while making CSocket calls.

Override the PumpMessages function so that it only looks for its own WM_TIMER messages and does not pick up other timer messages. This can be done by borrowing the CSocket::PumpMessages function from SOCKCORE.CPP and changing it as follows:
#if _MFC_VER == 0x0420


#define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE
#define WM_SOCKET_NOTIFY 0x0373
#define WM_SOCKET_DEAD 0x0374

#define _afxSockThreadState AfxGetModuleThreadState()

#endif

BOOL CMySocket::PumpMessages(UINT uStopFlag)
{
#if _MFC_VER != 0x0420
return CSocket::PumpMessages(uStopFlag);
#else

// The same socket better not be blocking in more than one place.
ASSERT(m_pbBlocking == NULL);

_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;

ASSERT(pState->m_hSocketWindow != NULL);

BOOL bBlocking = TRUE;
m_pbBlocking = &bBlocking;
CWinThread* pThread = AfxGetThread();

// This is not a timeout in the WinSock sense, but more
// like a WM_KICKIDLE to keep message pumping alive
UINT nTimerID = ::SetTimer(pState->m_hSocketWindow, 0,
m_nTimeOut, NULL);

if (nTimerID == 0)
AfxThrowResourceException();

BOOL bPeek = TRUE;

while (bBlocking)
{
TRY
{
MSG msg;
if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_SOCKET_NOTIFY, WM_SOCKET_DEAD, PM_REMOVE))
{
if (msg.message == WM_SOCKET_NOTIFY &&
(SOCKET)msg.wParam == m_hSocket)
{
if (WSAGETSELECTEVENT(msg.lParam) == FD_CLOSE)
{
break;
}
if (WSAGETSELECTEVENT(msg.lParam) == uStopFlag)
{
if (uStopFlag == FD_CONNECT)
m_nConnectError = WSAGETSELECTERROR(msg.lParam);
break;
}
}
if (msg.wParam != 0 ¦¦ msg.lParam != 0)
CSocket::AuxQueueAdd(msg.message, msg.wParam, msg.lParam);

bPeek = TRUE;
}
else if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_TIMER, WM_TIMER, PM_REMOVE))
{
break;
}

if (bPeek && ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (OnMessagePending())
{
// allow user-interface updates
pThread->OnIdle(-1);
}
else
{
bPeek = FALSE;
}
}
else
{
// no work to do -- allow CPU to sleep
WaitMessage();
bPeek = TRUE;
}
}
CATCH_ALL(e)
{
TRACE0("Error: caught exception in PumpMessage - continuing.\n");
bPeek = TRUE;
}
END_CATCH_ALL
}

::KillTimer(pState->m_hSocketWindow, nTimerID);

if (!bBlocking)
{
WSASetLastError(WSAEINTR);
return FALSE;
}
m_pbBlocking = NULL;

::PostMessage(pState->m_hSocketWindow,WM_SOCKET_NOTIFY,0,0);

return TRUE;

#endif // _MFC_VER
}


STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This bug has been fixed with the Visual C++ 4.2b patch. For more information on this patch, please see the following articles in the Microsoft Knowledge Base:


ARTICLE-ID: Q156934
TITLE : PATCH: Visual C++ 4.2b Patch

ARTICLE-ID: Q160491
TITLE : Information on Files Modified by VC42b Patch: Part 1 of 4

ARTICLE-ID: Q160496
TITLE : Information on Files Modified by VC42b Patch: Part 2 of 4

ARTICLE-ID: Q160505
TITLE : Information on Files Modified by VC42b Patch: Part 3 of 4

ARTICLE-ID: Q160506
TITLE : Information on Files Modified by VC42b Patch: Part 4 of 4




--------------------------------------------------------------------------------

Additional query words: CAsyncSocket CSocket hangs timer
Keywords : MfcSockets vcbuglist420 vcfixlist420 kbnetwork kbprg kbbuglist kbfixlist
Technology : kbMfc
Version : 4.2
Platform : NT WINDOWS
Issue type : kbbug
Solution Type : kbfix


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.


Last reviewed: September 19, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.




转移贴子到 Visual C++ Visual Basic Delphi C/C++ C++ Builder ASM 数据库开发 PowerBuilder ActiveX/COM 数据算法 软件工程 图形/游戏/多媒体 安全技术 网络/通讯 技术书籍 文件格式 C# XML 数据仓库 主页制作 图形处理 ASP PHP Perl Java Javascript JSP 软件使用 资源使用 软件注册 我看软件 寻找软件 行业软件 软件评测 Windows 95/98 Windows NT/2000 DOS Linux/Unix 硬件指南 程序人生 软件市场 程序员考试 人才热线 建议和意见 灌水乐园 走向海外 程序员杂志 | 贴子加分 | 删除贴子


回复贴子:


--------------------------------------------------------------------------------

我要回复: 有人参与讨论这个问题,请用EMail通知我


返回问题 | 关闭窗口





美达美简介 广告服务 英语步步高 程序员大本营 百联美达美科技有限公司 版权所有




masterlee 2001-05-28
  • 打赏
  • 举报
回复

CSDN首页 | 新闻聚焦 | 共享软件 | 俱乐部 | 开发文档 | 专家门诊 | 招聘求职 | Linux园地 | 程序员杂志
--------------------------------------------------------------------------------

我要回复 | 打印贴子 | 推荐给朋友 | 关闭窗口

主  题:有关MFC中CSocket类超时存在的BUG,讨论!!!
作  者:masterlee
所属论坛:Visual C++
问题点数:20
回复次数:0
人气指数:0
发表时间:2001-5-28 9:41:00

本人在使用CSocket类的过程中发现超时问题很难控制。
在MFC中提到如下:


FIX: CSocket Operation Hangs if a Timer is Active
Last reviewed: September 19, 1997
Article ID: Q154649
The information in this article applies to:
The Microsoft Foundation Classes (MFC) included with: Microsoft Visual C++, 32-bit Edition, version 4.2


SYMPTOMS
A call to CSocket Connect, Accept, Send, or Receive hangs if a timer is active.



CAUSE
CSocket operations are written using "pseudo-blocking." The WinSock API call is not a true blocking call, but if it doesn't return immediately then CSocket will call PumpMessages. PumpMessages looks for the FD_xxx notification and the CSocket function will not return until the FD_xxx notification arrives.

PumpMessages will not detect the socket notification if a timer is active because it looks for WM_TIMER messages first. When a WM_TIMER message arrives, the function doesn't look any further for other messages.

The PumpMessages function is looking for WM_TIMER messages because it sets up its own timer to cause the application to retry its socket calls and do periodic idle-time processing while waiting for the socket notification.



RESOLUTION
There are two possible resolutions:


Disable all timers while making CSocket calls.

Override the PumpMessages function so that it only looks for its own WM_TIMER messages and does not pick up other timer messages. This can be done by borrowing the CSocket::PumpMessages function from SOCKCORE.CPP and changing it as follows:
#if _MFC_VER == 0x0420


#define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE
#define WM_SOCKET_NOTIFY 0x0373
#define WM_SOCKET_DEAD 0x0374

#define _afxSockThreadState AfxGetModuleThreadState()

#endif

BOOL CMySocket::PumpMessages(UINT uStopFlag)
{
#if _MFC_VER != 0x0420
return CSocket::PumpMessages(uStopFlag);
#else

// The same socket better not be blocking in more than one place.
ASSERT(m_pbBlocking == NULL);

_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;

ASSERT(pState->m_hSocketWindow != NULL);

BOOL bBlocking = TRUE;
m_pbBlocking = &bBlocking;
CWinThread* pThread = AfxGetThread();

// This is not a timeout in the WinSock sense, but more
// like a WM_KICKIDLE to keep message pumping alive
UINT nTimerID = ::SetTimer(pState->m_hSocketWindow, 0,
m_nTimeOut, NULL);

if (nTimerID == 0)
AfxThrowResourceException();

BOOL bPeek = TRUE;

while (bBlocking)
{
TRY
{
MSG msg;
if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_SOCKET_NOTIFY, WM_SOCKET_DEAD, PM_REMOVE))
{
if (msg.message == WM_SOCKET_NOTIFY &&
(SOCKET)msg.wParam == m_hSocket)
{
if (WSAGETSELECTEVENT(msg.lParam) == FD_CLOSE)
{
break;
}
if (WSAGETSELECTEVENT(msg.lParam) == uStopFlag)
{
if (uStopFlag == FD_CONNECT)
m_nConnectError = WSAGETSELECTERROR(msg.lParam);
break;
}
}
if (msg.wParam != 0 ¦¦ msg.lParam != 0)
CSocket::AuxQueueAdd(msg.message, msg.wParam, msg.lParam);

bPeek = TRUE;
}
else if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_TIMER, WM_TIMER, PM_REMOVE))
{
break;
}

if (bPeek && ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (OnMessagePending())
{
// allow user-interface updates
pThread->OnIdle(-1);
}
else
{
bPeek = FALSE;
}
}
else
{
// no work to do -- allow CPU to sleep
WaitMessage();
bPeek = TRUE;
}
}
CATCH_ALL(e)
{
TRACE0("Error: caught exception in PumpMessage - continuing.\n");
bPeek = TRUE;
}
END_CATCH_ALL
}

::KillTimer(pState->m_hSocketWindow, nTimerID);

if (!bBlocking)
{
WSASetLastError(WSAEINTR);
return FALSE;
}
m_pbBlocking = NULL;

::PostMessage(pState->m_hSocketWindow,WM_SOCKET_NOTIFY,0,0);

return TRUE;

#endif // _MFC_VER
}


STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This bug has been fixed with the Visual C++ 4.2b patch. For more information on this patch, please see the following articles in the Microsoft Knowledge Base:


ARTICLE-ID: Q156934
TITLE : PATCH: Visual C++ 4.2b Patch

ARTICLE-ID: Q160491
TITLE : Information on Files Modified by VC42b Patch: Part 1 of 4

ARTICLE-ID: Q160496
TITLE : Information on Files Modified by VC42b Patch: Part 2 of 4

ARTICLE-ID: Q160505
TITLE : Information on Files Modified by VC42b Patch: Part 3 of 4

ARTICLE-ID: Q160506
TITLE : Information on Files Modified by VC42b Patch: Part 4 of 4




--------------------------------------------------------------------------------

Additional query words: CAsyncSocket CSocket hangs timer
Keywords : MfcSockets vcbuglist420 vcfixlist420 kbnetwork kbprg kbbuglist kbfixlist
Technology : kbMfc
Version : 4.2
Platform : NT WINDOWS
Issue type : kbbug
Solution Type : kbfix


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.


Last reviewed: September 19, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.




转移贴子到 Visual C++ Visual Basic Delphi C/C++ C++ Builder ASM 数据库开发 PowerBuilder ActiveX/COM 数据算法 软件工程 图形/游戏/多媒体 安全技术 网络/通讯 技术书籍 文件格式 C# XML 数据仓库 主页制作 图形处理 ASP PHP Perl Java Javascript JSP 软件使用 资源使用 软件注册 我看软件 寻找软件 行业软件 软件评测 Windows 95/98 Windows NT/2000 DOS Linux/Unix 硬件指南 程序人生 软件市场 程序员考试 人才热线 建议和意见 灌水乐园 走向海外 程序员杂志 | 贴子加分 | 删除贴子


回复贴子:


--------------------------------------------------------------------------------

我要回复: 有人参与讨论这个问题,请用EMail通知我


返回问题 | 关闭窗口





美达美简介 广告服务 英语步步高 程序员大本营 百联美达美科技有限公司 版权所有




masterlee 2001-05-28
  • 打赏
  • 举报
回复

CSDN首页 | 新闻聚焦 | 共享软件 | 俱乐部 | 开发文档 | 专家门诊 | 招聘求职 | Linux园地 | 程序员杂志
--------------------------------------------------------------------------------

我要回复 | 打印贴子 | 推荐给朋友 | 关闭窗口

主  题:有关MFC中CSocket类超时存在的BUG,讨论!!!
作  者:masterlee
所属论坛:Visual C++
问题点数:20
回复次数:0
人气指数:0
发表时间:2001-5-28 9:41:00

本人在使用CSocket类的过程中发现超时问题很难控制。
在MFC中提到如下:


FIX: CSocket Operation Hangs if a Timer is Active
Last reviewed: September 19, 1997
Article ID: Q154649
The information in this article applies to:
The Microsoft Foundation Classes (MFC) included with: Microsoft Visual C++, 32-bit Edition, version 4.2


SYMPTOMS
A call to CSocket Connect, Accept, Send, or Receive hangs if a timer is active.



CAUSE
CSocket operations are written using "pseudo-blocking." The WinSock API call is not a true blocking call, but if it doesn't return immediately then CSocket will call PumpMessages. PumpMessages looks for the FD_xxx notification and the CSocket function will not return until the FD_xxx notification arrives.

PumpMessages will not detect the socket notification if a timer is active because it looks for WM_TIMER messages first. When a WM_TIMER message arrives, the function doesn't look any further for other messages.

The PumpMessages function is looking for WM_TIMER messages because it sets up its own timer to cause the application to retry its socket calls and do periodic idle-time processing while waiting for the socket notification.



RESOLUTION
There are two possible resolutions:


Disable all timers while making CSocket calls.

Override the PumpMessages function so that it only looks for its own WM_TIMER messages and does not pick up other timer messages. This can be done by borrowing the CSocket::PumpMessages function from SOCKCORE.CPP and changing it as follows:
#if _MFC_VER == 0x0420


#define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE
#define WM_SOCKET_NOTIFY 0x0373
#define WM_SOCKET_DEAD 0x0374

#define _afxSockThreadState AfxGetModuleThreadState()

#endif

BOOL CMySocket::PumpMessages(UINT uStopFlag)
{
#if _MFC_VER != 0x0420
return CSocket::PumpMessages(uStopFlag);
#else

// The same socket better not be blocking in more than one place.
ASSERT(m_pbBlocking == NULL);

_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;

ASSERT(pState->m_hSocketWindow != NULL);

BOOL bBlocking = TRUE;
m_pbBlocking = &bBlocking;
CWinThread* pThread = AfxGetThread();

// This is not a timeout in the WinSock sense, but more
// like a WM_KICKIDLE to keep message pumping alive
UINT nTimerID = ::SetTimer(pState->m_hSocketWindow, 0,
m_nTimeOut, NULL);

if (nTimerID == 0)
AfxThrowResourceException();

BOOL bPeek = TRUE;

while (bBlocking)
{
TRY
{
MSG msg;
if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_SOCKET_NOTIFY, WM_SOCKET_DEAD, PM_REMOVE))
{
if (msg.message == WM_SOCKET_NOTIFY &&
(SOCKET)msg.wParam == m_hSocket)
{
if (WSAGETSELECTEVENT(msg.lParam) == FD_CLOSE)
{
break;
}
if (WSAGETSELECTEVENT(msg.lParam) == uStopFlag)
{
if (uStopFlag == FD_CONNECT)
m_nConnectError = WSAGETSELECTERROR(msg.lParam);
break;
}
}
if (msg.wParam != 0 ¦¦ msg.lParam != 0)
CSocket::AuxQueueAdd(msg.message, msg.wParam, msg.lParam);

bPeek = TRUE;
}
else if (::PeekMessage(&msg, pState->m_hSocketWindow,
WM_TIMER, WM_TIMER, PM_REMOVE))
{
break;
}

if (bPeek && ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (OnMessagePending())
{
// allow user-interface updates
pThread->OnIdle(-1);
}
else
{
bPeek = FALSE;
}
}
else
{
// no work to do -- allow CPU to sleep
WaitMessage();
bPeek = TRUE;
}
}
CATCH_ALL(e)
{
TRACE0("Error: caught exception in PumpMessage - continuing.\n");
bPeek = TRUE;
}
END_CATCH_ALL
}

::KillTimer(pState->m_hSocketWindow, nTimerID);

if (!bBlocking)
{
WSASetLastError(WSAEINTR);
return FALSE;
}
m_pbBlocking = NULL;

::PostMessage(pState->m_hSocketWindow,WM_SOCKET_NOTIFY,0,0);

return TRUE;

#endif // _MFC_VER
}


STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This bug has been fixed with the Visual C++ 4.2b patch. For more information on this patch, please see the following articles in the Microsoft Knowledge Base:


ARTICLE-ID: Q156934
TITLE : PATCH: Visual C++ 4.2b Patch

ARTICLE-ID: Q160491
TITLE : Information on Files Modified by VC42b Patch: Part 1 of 4

ARTICLE-ID: Q160496
TITLE : Information on Files Modified by VC42b Patch: Part 2 of 4

ARTICLE-ID: Q160505
TITLE : Information on Files Modified by VC42b Patch: Part 3 of 4

ARTICLE-ID: Q160506
TITLE : Information on Files Modified by VC42b Patch: Part 4 of 4




--------------------------------------------------------------------------------

Additional query words: CAsyncSocket CSocket hangs timer
Keywords : MfcSockets vcbuglist420 vcfixlist420 kbnetwork kbprg kbbuglist kbfixlist
Technology : kbMfc
Version : 4.2
Platform : NT WINDOWS
Issue type : kbbug
Solution Type : kbfix


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.


Last reviewed: September 19, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.




转移贴子到 Visual C++ Visual Basic Delphi C/C++ C++ Builder ASM 数据库开发 PowerBuilder ActiveX/COM 数据算法 软件工程 图形/游戏/多媒体 安全技术 网络/通讯 技术书籍 文件格式 C# XML 数据仓库 主页制作 图形处理 ASP PHP Perl Java Javascript JSP 软件使用 资源使用 软件注册 我看软件 寻找软件 行业软件 软件评测 Windows 95/98 Windows NT/2000 DOS Linux/Unix 硬件指南 程序人生 软件市场 程序员考试 人才热线 建议和意见 灌水乐园 走向海外 程序员杂志 | 贴子加分 | 删除贴子


回复贴子:


--------------------------------------------------------------------------------

我要回复: 有人参与讨论这个问题,请用EMail通知我


返回问题 | 关闭窗口





美达美简介 广告服务 英语步步高 程序员大本营 百联美达美科技有限公司 版权所有




16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧