服务器端应采用监听手段,使用listen

解决方案 »

  1.   

    代码如下:
    我在View中listen():
    // 初始化Winsock, 加载2.0版本的动态链接库
    if (WSAStartup(0x202, &wsaData) == SOCKET_ERROR)
    {
         CString m_str;
         m_str.Format("%d", WSAGetLastError());
         m_str = "SOCKET动态链接库加载失败!错误代码:" + m_str; 
         AfxMessageBox(m_str, MB_OK|MB_ICONSTOP);
         WSACleanup();
    }m_pSocket = new CListenSock();// 创建一个指向新生成的socket的指针if (m_pSocket->Create(PortDialog.m_nPort, SOCK_STREAM, NULL))
    {
        m_pSocket->Bind(PortDialog.m_nPort, NULL);
        this->pDoc->listen_socket = m_pSocket;
        this->pDoc->listen_socket->Listen();
    }说明:
    m_pSocket为View的成员变量;
    listen_socket是Doc的成员变量;
    在我自己新建的类中的OnAccept()中,有:
    void CListenSock::OnAccept(int nErrorCode) 
    {
        // 通知receive线程准备开始接收
      ((CMyServerApp*)AfxGetApp())->pServerView->AcceptStart.SetEvent();
        CAsyncSocket::OnAccept(nErrorCode);
    }
    这里的目的是激发线程执行。但是,程序并没有走到OnAccept()中。
      

  2.   

    首先,你要分清楚两种SOCEKT,一个是用于监听的,即你的VIEW里CREATE的那个,另一个是用于连接的SOCEKT,即你的DOC中的SOCKET,两者不是一回事,你的代码中把二者搞混了。建议你再派生出一个CConnectSocket类。
    做法如下:
      CListenSocket* pListen = new CListenSocket;
      pListen->Create(nPost, SOCK_STREAM, NULL);
      pListen->Listen(5);  CConnectSocket* pConnect = new CConnectSocket;
      pListen->Accept(*pConnect);这样你的CListenSocket的OnAccept会触发。另处,你的代码中Bind是不需要的。
      

  3.   

    那么Bind()的用处是什么?在MSDN中是这么说的:
        "Call this member function to associate a local address with the socket. This routine is used on an unconnected datagram or stream socket, before subsequent Connect or Listen calls. Before it can accept connection requests, a listening server socket must select a port number and make it known to Windows Sockets by calling Bind. Bind establishes the local association (host address/port number) of the socket by assigning a local name to an unnamed socket."
      

  4.   

    嗯,现在问题是这样的:我已经全部改正前面的错误。但是出了一个很奇怪的情况:    如果我的CListenSock是从CAsyncSocket类派生出来的,那么CListenSock类的OnAccept()始终没有反应;但是,如果我把它改为从CSocket派生,那么OnAccept()就可以走到!!真是见鬼了。不过我原来那个listen_socket就是从以CSocket为基类派生的CListenSock的对象,后来我想试一试是否能用CAsyncSocket类派生的子类的对象时,才出现了这次提问中出现的问题。    至于为什么要改变CListenSock的基类,也不是闲得没事,是因为如果OnAccept()可以运行到以后,并且开始Accept()后,程序总是会发生一个Assertion error,在sockcore.cpp中的这个部分(从line 495开始):" pSocket = CAsyncSocket::LookupHandle((SOCKET)wParam, FALSE);
     if (pSocket == NULL)
     {
      // Must be in the middle of an Accept call
      pSocket = CAsyncSocket::LookupHandle(INVALID_SOCKET, FALSE);
      ASSERT(pSocket != NULL);
      pSocket->m_hSocket = (SOCKET)wParam;
      CAsyncSocket::DetachHandle(INVALID_SOCKET, FALSE);
      CAsyncSocket::AttachHandle(pSocket->m_hSocket, pSocket, FALSE);
     }"
    在其中的line: "ASSERT(pSocket != NULL);"(line 512)出错,我不知道这个函数是干什么用的,因为MSDN里面对它只字未提。希望有人能知道并给与解答。
      

  5.   

    ASSERT()是一个宏,它假定()中的值是真值...如果不是真值就会debug错误,...
    我没用过CAsyncSocket,以前作socket只用过CSocket所以不知道LookupHandle是干什么用的,但是现象来看好像你的pSocket没有创建成功....
      

  6.   

    CAsyncSocket生的,好像你没有用CAsyncSocket::AsyncSelect
    (FD_ACCEPT)啊,你再试试看
    记得生成一个连接时也要
    AsyncSelect::AsyncSelect(FD_WRITE|FD_READ|FD_CLOSE)的我看你还不如用CSocket来,它是什么也不用管了
      

  7.   

    一、首先用一个端口扫描的工具(如iptools)察看一下,你的端口是否打开。
    二、如果没有打开,肯定是初始化没有成功。
    我猜原因可能是你没有调用AfxSockInit(....)
    因为我也经常遇到这个问题。:)
      

  8.   

    !!!!请注意!!!!
    你是否使用了多线程?并且在不同的线程中使用了同一个SOCEKT?如果是,那么问题就大了,VC有BUG,在线程之间传递MFC对象很容易出问题(尤其是SOCKET!)
    如果你一定要这样做,那你得使用DETACH和ATTACH,并且需要加一段补丁代码。如果只是创建SOCKET不成功,你可以在CREATE和LISTEN后调用GETLASTERROR
      

  9.   

    listen之前要加上CAsyncSocket::AsyncSelect(FD_ACCEPT);
      

  10.   

    回复人: punkboy(朋克小子) (  ) 信誉:100  2002-04-24 13:06:00  得分:0  
     
     
      listen之前要加上CAsyncSocket::AsyncSelect(FD_ACCEPT); 
     
    楼上说的不对,此句不是必需的。CREATE函数原形为:
    BOOL Create( UINT nSocketPort = 0, int nSocketType = SOCK_STREAM, long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE, LPCTSTR lpszSocketAddress = NULL );因此,不必另行调用SELECT
      

  11.   

    我刚才重新看了你的代码,发现:pListen->Create(nPost, SOCK_STREAM, NULL);把后面的NULL参数去掉,相信会没问题了。