配置CSocket 操作的超时时间.doc_第1页
配置CSocket 操作的超时时间.doc_第2页
配置CSocket 操作的超时时间.doc_第3页
配置CSocket 操作的超时时间.doc_第4页
配置CSocket 操作的超时时间.doc_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

配置Csocket 操作的超时时间最后修改 : 2005年8月24日本文的发布号曾为 CHS138692转载自/weidagang2046/articles/79285.htmlBOOL SetTimeOut(UINT uTimeOut)BOOL KillTimeOut()BOOL OnMessagePending()示例代码参考概要CSocket 操作,如“接收”(Receive)、“发送”(Send) 和“连接”(Connect) 均是阻塞操作,即要等到操作成功执行完毕或套接字上出现错误后,对这些函数的调用才有返回结果。在某些情况下,操作可能永远不能成功完成,这将导致程序无限循环等待操作完成。一种解决方法是通过编程限制完成操作使用的时间。本文将讨论这种方法。这种方法是设置定时,让它在操作时间过长时启动。此方法的关键在于处理定时器的方式。虽然操作是“阻塞的”,但仍然可以处理到达的消息。如果通过使用 SetTimer 设置定时器,那么可以查找 WM_TIMER 消息,并在收到该消息时终止操作。该过程中涉及的主要函数有:Windows API 调用函数::SetTimerMFC 函数:CSocket:OnMessagePendingCSocket:CancelBlockingCall为简单起见,可以在 Csocket 衍生类中封装该功能。警告:在进一步阅读本文之前,请注意在某些 MFC 版本中存在错误,会在试图使用定时器并重叠 OnMessagePending 时引起问题。这一问题将在下面的 Microsoft Knowledge Base 文章中进行讨论:137632 (/kb/137632/EN-US/) 错误:定时器激活时未调用 OnMessagePending本文仅适用于 Visual C+ 的 1.52、1.52b、2.1 和 2.2 版本。如果使用的是这些 Visual C+ 版本之一,则还需要实施所提供的变通解决方法。本文最后部分显示提供这种超时功能的类的示例代码。以下内容讲述由该类实现的函数。BOOL SetTimeOut(UINT uTimeOut)调用此函数之后紧接着调用 CSocket 函数(如 Receive、Send 和 Accept)。uTimeOut 参数是以毫秒为单位指定的。之后,进行定时器的设置。如果设置定时器失败,那么函数返回 FALSE。有关详细情况,请参阅 SetTimer 函数的 Windows API 文档。BOOL KillTimeOut()在完成阻塞操作后,必须调用此函数。此函数删除用 SetTimeOut 设置的定时器。如果调用 KillTimer 失败,则返回 FALSE。有关详细情况,请参阅 KillTimer 函数的 Windows API 文档。BOOL OnMessagePending()这是一个虚拟回调函数,在等待操作完成时由 CSocket 类进行调用。此函数给您提供处理传入消息的机会。此实施过程检查用 SetTimeOut 调用函数设置的定时器的 WM_TIMER 消息。如果收到消息,则调用 CancelBlockingCall 函数。有关 OnMessagePending 和 CancelBlockingCall 函数详细的信息,请参阅 MFC 文档。请注意:调用 CancelBlockingCall 函数 将导致操作失败,而且 GetLastError 函数返回 WSAEINTR(表示操作中断)。下面是使用该类的一个例子: . 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 timer. 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? / . / / HEADER FILE / class CTimeOutSocket : public CSocket public: BOOL SetTimeOut(UINT uTimeOut); 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); CSOCKET的超时设置和UDP发送接收 使用CSoket多次了,但对于它的block模式的理解并不是很深入。昨天使用csoket的udp多发测试(server接到数据后,需要通过某种方式将数据发送到client,使用tcp方式比较可靠,我一直这样用的,但是比较费时,需要逐一发送),发现了问题: 1)create(),sendto(),receivefrom(). 2)其中,发送方一直定时发送数据无问题; 3)而接收方,通过一个单独的接收线程实现( 注意:csocket不能跨线程使用!主线程中socket create()后,detach()并将sock作为lpvoid传入接收线程 )。代码如下: /处理接收数据UINT CSockSvr:DealSvrRevData(LPVOID lParam) .DWORD dwError;TCHAR cBuff1000;CString sIP;UINT uPort;for(;!pDlg-m_bExit;) :memset( cBuff,0,sizeof(cBuff) ); / 如果没有接到数据,一直等待。 / 阻塞模式的弊端:在退出时候,通过CancelBlockingCall int iRst=SockSvr.ReceiveFrom( cBuff,sizeof(cBuff),sIP,uPort,0 ); if( iRst!=SOCKET_ERROR ) CString sTemp=cBuff; TRACE1( _T(rn Rev Data: %srn),sTemp ); else dwError=GetLastError(); TRACE1( _T(rn Rev Data Error code: %drn),dwError ); :Sleep(200);return 0; 问题:如果发送方没有数据,SockSvr.ReceiveFrom()会一致处于等待状态,导致整个处理接收线程的停止,如果用户需要退出/结束程序,无法正确释放资源(无法关闭在线程函数重打开的socket-不能跨线程操作socket,无法关闭线程),造成系统memory leak. 针对这种问题,微软的解决办法是:/default.aspx?scid=kb;zh-cn;138692,经过测试,在socket进行connect()的时候不好用。后来,结合微软的办法,我通过自定义的定时器,实现了block超时间后自动退出的功能 #if !defined(AFX_TIMEOUTSOCK_H_19897A81_4EAF_4005_91FD_DC3047725139_INCLUDED_)#define AFX_TIMEOUTSOCK_H_19897A81_4EAF_4005_91FD_DC3047725139_INCLUDED_#if _MSC_VER 1000#pragma once#endif / _MSC_VER 1000/ TimeOutSock.h : header file/*CSocket 操作,如接收(Receive)、发送(Send) 和连接(Connect) 均是阻塞操作,即要等到操作成功执行完毕或套接字上出现错误后,对这些函数的调用才有返回结果。某些情况下,操作可能永远不能成功完成,这将导致程序无限循环等待操作完成。一种解决方法是通过编程限制完成操作使用的时间。本文将讨论这种方法。*/ CTimeOutSock command targetclass CTimeOutSock : public CSocket/ Attributespublic:/ Operationspublic:CTimeOutSock();virtual CTimeOutSock();/ Overridespublic:/ ClassWizard generated virtual function overrides/AFX_VIRTUAL(CTimeOutSock)public:virtual BOOL OnMessagePending();/AFX_VIRTUAL/ Generated message map functions/AFX_MSG(CTimeOutSock) / NOTE - the ClassWizard will add and remove member functions here./AFX_MSG/*/定时器设置block超时 不是很好用。徐卫话 2006.4.19CSocket 操作,如接收(Receive)、发送(Send) 和连接(Connect) 均是阻塞操作,即要等到操作成功执行完毕或套接字上出现错误后,对这些函数的调用才有返回结果。某些情况下,操作可能永远不能成功完成,这将导致程序无限循环等待操作完成。一种解决方法是通过编程限制完成操作使用的时间。本文将讨论这种方法。*/ 自己计算时间的办法 OKpublic: BOOL SetTimeOut(UINT uTimeOut=1000); BOOL KillTimeOut();private: LONGLONG m_llDtStart; UINT m_uTimeOut;/ Microsoft Visual C+ will insert additional declarations immediately before the previous line.#endif / !defined(AFX_TIMEOUTSOCK_H_19897A81_4EAF_4005_91FD_DC3047725139_INCLUDED_) / TimeOutSock.cpp : implementation file/#include stdafx.h#include NetBroad.h#include TimeOutSock.h#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE = _FILE_;#endif/ CTimeOutSockCTimeOutSock:CTimeOutSock()CTimeOutSock:CTimeOutSock()/ Do not edit the following lines, which are needed by ClassWizard.#if 0BEGIN_MESSAGE_MAP(CTimeOutSock, CSocket)/AFX_MSG_MAPEND_MESSAGE_MAP()#endif / 0/ CTimeOutSock member functions/设置超时BOOL CTimeOutSock:SetTimeOut(UINT uTimeOut)/get start cntLARGE_INTEGER llCnt;:QueryPerformanceCounter(&llCnt);m_llDtStart=llCnt.QuadPart;m_uTimeOut=uTimeOut; return TRUE;/删除超时参数BOOL CTimeOutSock:KillTimeOut()m_llDtStart=0;/表明取消计时return TRUE;/检查是否超时间BOOL CTimeOutSock:OnMessagePending()/ TODO: Add your specialized code here and/or call the base class/*MSG msg; if(:PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE) if (msg.wParam = (UINT) m_nTimerID) / Remove the message and call CancelBlockingCall. :Pe

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论