问题1:如果是在Accept后触发,那么在OnAccept里面应该响应什么呢?是否Accept失败也能触发OnAccept?
问题2:CAsyncSocket是非阻塞的,如何实现获取连接?
坐等高人详细解释CAsyncSocket的服务器端实现

解决方案 »

  1.   

    问题1: 答案:  有客户端请求连接时响应, Accept失败跟触发OnAccept没有关系,Accept只是负责判断是否监听成功,然后进行通信。问题2:答案:  可以在OnAccept里捕获客户端的连接,然后获取客户端的IP,下面是获取连接的代码//有连接时触发,负责监听客户端
    void CDistributor::OnAccept(int nErrorCode)
    {
    CClientSocket *psocket = new CClientSocket(); if (Accept(*psocket))//如果监听成功,就可以获取客户端的信息进行通信了
    {
    CString str1;
    CString str2(_T("客户端:"));
    unsigned int m_port=7000;
    psocket->GetPeerName(str1,m_port)//获取到指定IP和端口
    psocket->AsyncSelect(FD_READ|FD_WRITE);//投递事件               //下面的处理就看你了呵呵
                   
    CAsyncSocket::OnAccept(nErrorCode);
    }http://www.cnblogs.com/wqj1212/archive/2009/03/18/1415786.html    博客园,这个比较详细呵呵!   
      

  2.   

    那岂不是要时时监听,CAsyncSocket是非阻塞的难道要
    while(1)
    {
    Listen(5);
    }
    要不然,我怎么知道客户端什么时候连接,等它连接时服务端程序都执行完了还怎么监听啊
      

  3.   

    Listen一次即可,以后客户端每次connect。OnAccept都会被触发
      

  4.   

      然而,最不容易被初学Socket编程的人理解的,也是本文最要提醒的一点是,客户方在使用CAsyncSocket::Connect()时,往往返回一个WSAEWOULDBLOCK的错误(其它的某些函数调用也如此),实际上这不应该算作一个错误,它是Socket提醒我们,由于你使用了非阻塞Socket方式,所以(连接)操作需要时间,不能瞬间建立。既然如此,我们可以等待呀,等它连接成功为止,于是许多程序员就在调用Connect()之后,Sleep(0),然后不停地用WSAGetLastError()或者CAsyncSocket::GetLastError()查看Socket返回的错误,直到返回成功为止。这是一种错误的做法,断言,你不能达到预期目的。事实上,我们可以在Connect()调用之后等待CAsyncSocket::OnConnect()事件被触发,CAsyncSocket::OnConnect()是要表明Socket要么连接成功了,要么连接彻底失败了。至此,我们在CAsyncSocket::OnConnect()被调用之后就知道是否Socket连接成功了,还是失败了。
      类似的,Send()如果返回WSAEWOULDBLOCK错误,我们在OnSend()处等待,Receive()如果返回WSAEWOULDBLOCK错误,我们在OnReceive()处等待,以此类推。
      还有一点,也许是个难点,那就是在客户方调用Connect()连接服务方,那么服务方如何Accept(),以建立连接的问题。简单的做法就是在监听的Socket收到OnAccept()时,用一个新的CAsyncSocket对象去建立连接,例如: void CMySocket::OnAccept( int ErrCode )
     {
           CMySocket* pSocket = new CMySocket;
           Accept( *pSocket );
     }
        于是,上面的pSocket和客户方建立了连接,以后的通信就是这个pSocket对象去和客户方进行,而监听的Socket仍然继续在监听,一旦又有一个客户方要连接服务方,则上面的OnAccept()又会被调用一次。当然pSocket是和客户方通信的服务方,它不会触发OnAccept()事件,因为它不是监听Socket。
      

  5.   


    不需要啊,初始化之后listen一次就够了,只需要设置你要监听的客户端套接字数就可以了//初始化分发服务器Socket
    void CDistributor::CreateServer()
    {
    if(this->m_hSocket == INVALID_SOCKET)//服务器处于未连接状态
    {
    bool bflag = this->Create(65432,SOCK_STREAM,FD_ACCEPT);
    if(bflag==false)
    {
    AfxMessageBox(_T("服务器建立套接字,请确保端口未被占用"));
    this->Close();
    }
    else
    {
    //设置为32K
    int nSendBuf=60*1024;
    //设置套接口
    setsockopt(this->m_hSocket,SOL_SOCKET,SO_SNDBUF,(const char*)&nSendBuf,sizeof(nSendBuf));
    }
    if(!this->Listen(100))//监听客户端连接数
    {
    int nerrorcode = this->GetLastError();
    if (nerrorcode==WSAEWOULDBLOCK)
    {
         AfxMessageBox(_T("Socket Error"));
         this->Close();
         PostQuitMessage(0);
    }
    } }
    }
      

  6.   

    最好是自己写代码,然后加断点测试下,然后你看是不是这样的,只要服务器套接字正确创建之后,然后设置监听的客户端个数,重定义OnAccept函数,客户端每连接一次OnAccept都会执行,客户端可以写个for循环反复连下,而Listen是套接字初始化的时候就设置了的,所以之后通信的操作跟它没关系了。