CSocket如何设置接收超时啊,网上根本找不到相关的资料,希望大家帮下我,给一点意见,谢谢了

解决方案 »

  1.   

    CSocket好像不行,要用winsock的
    struct timeval rcvto;
     int tolen=sizeof(struct timeval);
     rcvto.tv_sec=1000;
     rcvto.tv_usec=0;
     setsockopt(s,SOL_SOCKET,SO_RCVTIMEO,(char *)&rcvto,tolen);
      

  2.   

    啊,我的已经全部使用 CSocket 了,要改的话工程量很大,而且还要测试,现在时间很短,我担心来不及了
      

  3.   

            int nSelectRet;
    TIMEVAL tv01 = {0, 1};//1ms钟延迟,实际为0-10毫秒 
    FD_SET fdr = {1, sockSrv};
    nSelectRet = select(0, &fdr, NULL, NULL, &tv01);//检查可读状态 
      

  4.   

    看一下CSocket定义:
    class CSocket : public CAsyncSocket
    {
    ...
    };CAsyncSocket封装的是WSAAsyncSelect模型,是基于windows消息的异步模型,没有超时机制。
      

  5.   

    CSocket里有public的int m_nTimeOut;不清楚用途。
    其父类CAsyncSocket有public的SOCKET m_hSocket;直接用楼上setsockopt(m_hSocket,SOL_SOCKET,SO_RCVTIMEO,(char *)&rcvto,tolen);应该可以。
      

  6.   


    停止什么?是要关闭socket么,你closesocket一下,recv会马上返回的啊。
      

  7.   

    SO_RCVTIMEO是设接受的timeout.另外msdn上的另外的方法:Knowledge Base  How To Configure a Time-Out on a CSocket OperationPSS ID Number: 138692Article Last Modified on 7/15/2004
    --------------------------------------------------------------------------------
    The information in this article applies to:
    Microsoft Foundation Classes (MFC) 1.0--------------------------------------------------------------------------------This article was previously published under Q138692
    SUMMARY
    CSocket operations, such as Receive, Send, and Connect, are blocking operations in the sense that a call to these functions will not return until it has successfully completed or an error on the socket has occurred. Under some circumstances, the operation might never complete successfully and your program will loop forever while waiting for this completion. It might be a good idea to programmatically limit the amount of time allowed for the operation to complete. This article discusses one way to do it. 
    MORE INFORMATION
    One approach would be to set a timer that fires when the operation has taken too long. The key to this approach is in how the timer is handled. Although the operation is "blocking," you still have the ability to handle messages that arrive. If you set a timer by using SetTimer, then you can look for the WM_TIMER message, and abort the operation when it arrives. The primary functions involved in this process are: 
    The Windows API call: ::SetTimer 
    The MFC functions: CSocket::OnMessagePending
    CSocket::CancelBlockingCall 
    For simplicity, this functionality can be encapsulated in your CSocket- derived class. WARNING: Before reading further, note that there is a bug in some versions of MFC that will cause problems if you attempt to use a timer and override OnMessagePending. This problem is documented in the following Microsoft Knowledge Base article: 
    137632 BUG: OnMessagePending Not Called When a Timer Is Active This article applies only to versions 1.52, 1.52b, 2.1, and 2.2 of Visual C++. If you are using one of these versions of Visual C++, then you will also need to implement the workaround that is supplied. The sample code for a class that provides this time-out capability is included at the end of this article. The functions implemented by the class are described in the following sections of this article. 
    BOOL SetTimeOut(UINT uTimeOut)
    This would be called immediately before calling the CSocket function (for example, Receive, Send, and Accept). The uTimeOut parameter is specified in milliseconds. The following implementation simply sets up the timer. This function returns FALSE if the attempt to set the timer failed. See the Windows API documentation on the SetTimer function for further details. 
    BOOL KillTimeOut()
    This function needs to be called after the completion of the operation that was blocking. It removes the timer that was set up with SetTimeOut. It returns FALSE if the call to KillTimer failed. See the Windows API documentation on the KillTimer function for further details. 
    BOOL OnMessagePending()
    This is a virtual callback that is called by the CSocket class when it is waiting for an operation to complete. It gives you the opportunity to do something with incoming messages. This implementation checks for the WM_TIMER message for the timer set with the SetTimeOut call. And if it arrives then it invokes the CancelBlockingCall function. See the MFC documentation on the OnMessagePending and CancelBlockingCall functions for details. Please note that by calling CancelBlockingCall, you will cause the operation to fail and GetLastError will return WSAEINTR (indicating an interrupted operation). Here is an example use of this class: 
       ...
       CTimeOutSocket sockServer;
       CAcceptedSocket sockAccept;   sockServer.Create(777);
       sockServer.Listen();   // Note the following sequence:
       //  SetTimeOut
       //  <operation which might block>
       //  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?
         // 
       }
       ...

    Sample Code
       // 
       // 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);
       }

    REFERENCES
    For more information on the SetTimer and KillTimer functions, please see the Windows API Help file. For more information on the CSocket class and its member functions, please see: 
    In Visual C++ 2.x - The MFC Help file.
    In Visual C++ 1.5x - The Mfcext.hlp help file, which can be found on the compact disc in the \Msvc15\Help directory. Additional query words: timingKeywords: kbAPI kbcode kbhowto kbnetwork kbTimer kbWinsock KB138692 
    Technology: _IKkbbogus kbAudDeveloper kbMFC 
      

  8.   

    socket超时一直是个小问题。
    可以设置一个成员变量,接收到包就清零,否则就增加;
    当然,最科学的方法是做心跳包,每个一定的时间就像对方发送请求包,对方返回,不需要内容,但是,需要开启线程,逻辑上处理也比较发杂
      

  9.   

    我的CSocket是线程里定义的,要外部改变它变量怎么传出去呢?难道线程里再创建线程? 
      

  10.   

    观注下,这个,我遇到同样的问题。
    用了9楼的方法去处理,OnMessagePending()消息是发了,但int CTimeOutSocket::Receive(void* lpBuf, int nBufLen, int nFlags) 
    {
     SetTimeOut(10000);
     int nRecv = CSocket::Receive(lpBuf, nBufLen, nFlags);
     KillTimeOut();
     return nRecv;
    }这CTimeOutSocket::Receive()这个函数怎么能得到返回值。