FD_SET(client,&rmask);select(0,&rmask,0,0,&timeout);FD_ISSET(s,&rmask); //当数据到达和关闭是都为TRUE,怎么区分?(javanew

解决方案 »

  1.   

    清空了,我看过一个例子,好象要通过MSG_PEEK来区分,是吗?这和windows的Event模型有什么区别?
      

  2.   

    c/sc中的socket关闭了。s中还是FD_ISSET()还是为真,readfds: If listen has been called and a connection is pending, accept will succeed. 
    Data is available for reading (includes OOB data if SO_OOBINLINE is enabled). 
    Connection has been closed/reset/terminated. 这三种情况怎么区分呢?
      

  3.   

    to 楼主,你问题解决了吗?我看到有人说要 recv 一下才可以。
    我也知道 recv 一下可以判断,int nRecv = recv()
    if(nRecv == 0)
    {
      //没有可读的数据
    }但是,我不相信 Select 模型会是这样的啊。
    我开了一个线程专门的 select ,
    select 到了FD_ISSET()为真,就发送可读消息。现在的问题是,c 端的 socket 已经关闭了,但FD_ISSET()还是为真。
    所以我的线程还是不段的 发送消息。结果是可以想象的,阻塞了。我现在要在 select 线程中就判断出来 是不是可读?你有办法吗?
      

  4.   

    是这样的,
    看看《windows 网络编程技术》第8章
      

  5.   

    to yanhuahui :我的模型就是书上看来的啊。
    是一样的啊。我感觉书上的当 socket(c端)关闭后,FD_ISSET()还是为真。
    所以我想问问实际是怎么用的。不过我的问题基本解决了。
      

  6.   

    框架是这样的。//Select model 
    DWORD WINAPI SelectThread(LPVOID lpvoid)
    {
     while(true)
     {
       DWORD word = ::WaitForSingleObject(::g_handle, 0);
      if(word == WAIT_OBJECT_0)
     {
      #ifdef _DEBUG
         ::MessageBox(NULL, "结束 Select Thread!", "Message Box",   
         MB_OK); 
      #endif
         return 1;
      }   if(socket != 0)
       {
          FD_ZERO(&readfds);
          FD_SET(socket, &readfds);

          n = ::select(0, &readfds, NULL, NULL, &Timeval);
         if(n == SOCKET_ERROR)
        {
        #ifdef _DEBUG
          ::MessageBox(NULL, "Select fail !", "Messsage Box", MB_OK);
        #endif
          return 0;
        }
        if(n > 0)
        {
          if(FD_ISSET(socket, &readfds))
          {
    //{{可读, 发送消息 UM_READABILITY
    CChat_ServerApp * pwnd = (CChat_ServerApp *)::AfxGetApp();
    #if 1
    ::SendMessage(pwnd->m_pMainWnd->m_hWnd,UM_READABILITY, 
        (WPARAM)pSocket, NULL);
    #else
    ::PostMessage(pwnd->m_pMainWnd->m_hWnd,UM_READABILITY, 
        (WPARAM)pSocket, NULL);
    #endif
    //}}可读, 发送消息 UM_READABILITY
            }
       }
     }
    }//主线程
    int nReceive = recv();
    if(nReceive == 0)
    {
      ::SetEvent(g_handle);
      return ;
    }
      

  7.   

    我不知道你的断线是设么意思。据我所知如果用socket的tcp/ip建立的连接。
    那么一方断开了连接,另一方是可以收到消息的,从而知道连接断了。
      

  8.   

    下面代码是《网络编程》书中例子的判断连接是否断的代码,请参考
    BOOL bConnDropped = FALSE;
    INT iRet = 0;
    BOOL bOK = TRUE;

    struct timeval timeout = { 0, 0 };
    fd_set readSocketSet;

    FD_ZERO( &readSocketSet );
    FD_SET( m_hSocket, &readSocketSet );

    iRet = ::select( 0, &readSocketSet, NULL, NULL, &timeout );
    bOK = (iRet > 0);

    if(bOK){
    bOK = FD_ISSET( m_hSocket, &readSocketSet );
    }

    if( bOK ){
    CHAR szBuffer[1] = "";
    iRet = ::recv( m_hSocket, szBuffer, 1, MSG_PEEK );
    bOK = ( iRet > 0 );
    if( !bOK ){
    INT iError = ::WSAGetLastError();
    bConnDropped = ( ( iError == WSAENETRESET ) ||
    ( iError == WSAECONNABORTED ) ||
    ( iError == WSAECONNRESET ) ||
    ( iError == WSAEINVAL ) ||
    ( iRet == 0 ) ); //Graceful disconnect from other side.
    }
    }
      

  9.   

    我现在用的方法是这样的,如果收到接收或断开的消息后,用
    iRet=receive(...MSG_PEEK)先偷看一下是否有数据来,如果没有数据来,则认为断线了,反之是有数据到来的消息
      

  10.   

    那就是说,还是要 recv 一下才知道了。
    郁闷,我也是暂时是这样解决的。我觉得有更好的方法。继续搜索。
      

  11.   

    其他方法有啊,比如事件模型,消息驱动,但我想知道这于select有什么区别
      

  12.   

    这是几种模型啊,怎么?关于完成端口模型 事件选择 异步选择 还有重叠IO 模型什么的,
    目前我所做的一个小玩意里我用到了 select 模型,
    其他的几种模型效率要高,《Windows 网络编程技术》中有讲。其实在我初步的看来,就思想上理解来讲,(我说我个人的观点,不对的地方请指正)
    :我个人认为,我也试图把 select 模型 转变为 重叠IO 模型的,
    看了一下,我觉得在思想上,我比较快的理解了(很肤浅的理解了)重叠IO模型,我觉得几种模型在思想上比较接近(个人观点),虽然实现各有各的不同。效率也不一样(书上说的,没有实际测试)。