为何我的WSAAsyncSelect函数,在接受了第一个客户端连接以后,被其映射的消息函数就再也未被调用过?但是客户端提仍然提示已正确连接到服务器,但不能发送接收消息.
我的WSAAsyncSelect是这样调用的:
WSAAsyncSelect(ServerSock, AfxGetMainWnd()->m_hWnd, WM_CLIENT_ARRIAY, FD_ACCEPT);
WM_CLIENT_ARRIAY消息被映射到OnAccept函数,但其仅在第一个客户端连入时执行一次,以后再有客户端连入时就跟踪不到它执行了,是不是每次接受了客户端连接以后都要再次重析注册一次WSAAsyncSelect函数才行?
我的程序哪里有不妥之处,请各位哥哥姐姐们帮忙看看,给点意见.

解决方案 »

  1.   

    你调用listen函数时是不是做了客户端队列的限制?就是listen的第二个参数,表示等待连接队列的客户端个数
      

  2.   

    没有..我用的是listen(ServerSock, SONOMAX)参数.
      

  3.   

    一定是你onaccept这个函数在第一次onaccept后就一直在处理,而没有开线程。
      

  4.   

    你是不是把监听socket和连接socket搞混了
      

  5.   

    我没有处理FD_READ,FD_WRITE消息.我的OnAccept函数是这么调用的:
    void CServerDlg::OnNetConn(WPARAM wParam, LPARAM lParam)
    {

    int iEvent = WSAGETSELECTEVENT(lParam); 
    //得到发出此事件的客户端套接字 
    char buf[20];
    SOCKET pSock = (SOCKET)wParam; 
    switch(iEvent) 

    case FD_ACCEPT: //客户端连接请求 

    Thread_Data *Td = new Thread_Data;
    Td->sock = pSock;
    Td->pCc  = new CClient();
    unsigned long hHwnd;
    CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ProcessClient, 
    (LPVOID)Td, CREATE_ALWAYS, &hHwnd);
    break; 
    }
    case FD_CLOSE:
    break;
    default: break; 
    }
    }函数一创建完了线程就返回了呀,不存在一直处理的问题.
    我的网络初始化函数是这样调用的:
    bool CServerDlg::InitNetPara()
    {
    WORD wVersionRequested;// 定义版本信息变量
        WSADATA wsaData;//定义数据信息变量
        
        wVersionRequested = MAKEWORD(1,1);//给版本信息赋值
       
    int ret = WSAStartup(wVersionRequested, &wsaData);
    if ( ret != 0){
    AfxMessageBox(_T("初始化套接字失败!")); 
    return FALSE; 
    } ServerSocket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    if (ServerSocket ==INVALID_SOCKET){
    AfxMessageBox(_T("创建套接字失败!")); 
    closesocket(ServerSocket); 
    WSACleanup(); 
    return FALSE; 
    }

    sockaddr_in sin ;

    sin.sin_addr.s_addr = htons(INADDR_ANY);
    sin.sin_family = AF_INET;
    sin.sin_port= htons( PORT);
    if( bind(ServerSocket,(const struct sockaddr*)&sin, 
    sizeof(sockaddr)) == SOCKET_ERROR){
    AfxMessageBox(_T("绑定地址失败!")); 
    closesocket(ServerSocket); 
    WSACleanup(); 
    return FALSE; 
    } WSAAsyncSelect(ServerSocket, AfxGetMainWnd()->m_hWnd , WM_CLIENT_ARRIAY, FD_ACCEPT); 
    listen(ServerSocket, SOMAXCONN); //监听网络事件
    return true;
    }
      

  6.   

    你对WSAAsyncSelect模式理解有误,触发FD_ACCEPT事件后要调用accept函数;
    而且,你应把已连接套接口传入Td->sock,而不是把监听套接口传入Td->sock。
      

  7.   

    像这样:
    void CServerDlg::OnNetConn(WPARAM wParam, LPARAM lParam)
    {

    int iEvent = WSAGETSELECTEVENT(lParam); 
    //得到发出此事件的客户端套接字 
    char buf[20];
    SOCKET pSock = (SOCKET)wParam; 
    switch(iEvent) 

    case FD_ACCEPT: //客户端连接请求 

    Thread_Data *Td = new Thread_Data;
    Td->sock = accept(pSock,.....);
    ;
      

  8.   

    up,还补充一点,WSA系列网络函数最好这样初始化:
      WSADATA wsaData;
      ASSERT(WSAStartup(MAKEWORD(2,2), &wsaData)==0);
      

  9.   

    这样调用以后,发现程序会不断的调用OnAccept函数...
      

  10.   

    你的代码里面怎么没有 accept呢?好奇怪啊我觉得问题应该出现在你的ProcessClient线程里,这个线程是做什么的?既然都用WSAAsyncSelect了为什么还要另外开线程呢??
      

  11.   

    你的用法有问题, 我下面做为参考.
    listen(hListenSocket, 5);
    WSAAsyncSelect(hListenSocket, m_hWnd, WM_ACCEPT, FD_ACCEPT | FD_CLOSE);LRESULT CXxx::OnAccept(WPARAM wParam, LPARAM lParam)
    {
         SOCKET hClientSocket;
         int nEvent = WSAGETSELECTEVENT(lParam);
         switch (nEvent)
         {
         case FD_ACCEPT:
             hClientSocket = accept(wParam, NULL, NULL);
             // 发出另外一个消息事件请求
             WSAAsyncSelect(hClientSocket, m_hWnd, WM_CLIENT, FD_RECV | FD_WRITE | FD_CLOSE);
             break;
         case FD_CLOSE:
             .....
             break;
         default:
             break;
         }
         return 0;
    }
    LRESULT CXxx::OnClient(WPARAM wParam, LPARAM lParam)
    {
        int nRet;
        int nEvent = WSAGETSELECTEVENT(lParam);
        switch (nEvent)
        {
         case FD_RECV:
             nRet = recv(wParam, buff, sizeof(buff),......);
             ....
             break;
         case FD_WRITE:
             .....
         default:
             ...
         }     
         return 0;
    }上面是一个简单的基于异步消息的TCP服务代码框架.这样做服务器,性能比较低.
             
          
             
         
         
      

  12.   

    另外,代码中的m_hWnd要根据实际情况而定.
      

  13.   

    唉,我的程序用到了ADO,如果不为其开线程,客户端的消息请求和当前状态,极难保存,只好为每个客户端独立创建一个Recordset对象,但是线程中无法把com+对象实例化,没有办法,只能在主程序中实便化CClient类,再传给线程处理。做成异步的,就是不要想让它阻塞等待连入而已了。
    程序经修改是这样的了:
    void CServerDlg::OnNetConn(WPARAM wParam, LPARAM lParam)
    {

    int iEvent = WSAGETSELECTEVENT(lParam); 
    //得到发出此事件的客户端套接字 
    char buf[20];
    struct sockaddr sa_in;
    int sa_len;
    SOCKET pSock = (SOCKET)wParam; 
    SLinkList *node = new SLinkList;
    switch(iEvent) 

    case FD_ACCEPT: //客户端连接请求 
    {
    Thread_Data *Td = new Thread_Data;
    Td->sock = WSAAccept(pSock, &sa_in, &sa_len, NULL, NULL);
    Td->pCc  = new CClient();
    node->sock = Td->sock;
    node->C_Object = Td->pCc;
    unsigned long hHwnd;
             node->Thread_hWnd=CreateThread(NULL, NULL, 
    (LPTHREAD_START_ROUTINE)ProcessClient, 
    (LPVOID)Td, CREATE_ALWAYS, &hHwnd);
    this->LList->InsertNode(node);
    break; 
    }
    case FD_CLOSE:
    this->LList->DeleteNode(pSock);
    break;
    default: break; 
    }