我是自己封装的类库  做了tcp的server一个类  不能使用mfc类  也没有窗口  请问怎样做?
用WSAEventSelect可以实现吗? 应该怎样做呢  哪位有这方面的例子? 谢谢!

解决方案 »

  1.   

    建议你看看ACE库,它有非阻塞的封装
    ACE-5.4\ACE_wrappers\examples\Connection\non_blocking
      

  2.   

    我在程序里开了一个线程  然后用WSAWaitForMultipleEvents的时候返回的index-=WSA_WAIT_EVENT_0 总是一个很大的数  不在事件数组范围之内  这是为什么呢?  还有捕捉FD_READ消息总是捕捉不到。
      

  3.   

    已经写好了的库,你可以直接使用了。
    源码请参考
    http://www.vczx.com/article/show.php?id=1041
      

  4.   

    我对这方面还不熟悉  请大家赐教下边的代码都有什么问题?
    unsigned _stdcall Recieve(VOID* pParam)
    {
    CFsTcpClient* client = NULL;
    client = (CFsTcpClient*)pParam;
    client->Recv();
    return 0;
    }
    VOID  CFsTcpClient::SrvRcv()
    {
    ULONG hThread = _beginthreadex(NULL,0,Recieve,this,0,NULL);
    } //

    INT  CFsTcpClient::Recv()
    {
    WSAEVENT eventList[1];

    eventList[0] = WSACreateEvent();

    WSAEventSelect(iSock,eventList,FD_READ | FD_WRITE | FD_CONNECT | FD_ACCEPT | FD_CLOSE);  
    if( !WSAResetEvent(eventList[0]) )
    return -1;

    INT iIndex = 0;
    while( (iIndex = WSAWaitForMultipleEvents(1,eventList,
    false,1000,true)) == WSA_WAIT_FAILED)
    {
    iIndex -= WSA_WAIT_EVENT_0;
    WSANETWORKEVENTS type;
    WSAEnumNetworkEvents(iSock,eventList[iIndex],&type);
    if(type.lNetworkEvents & FD_READ)
    {
    fd_set fdsSocks;
    struct timeval stTimeout;

    memset(szOutBuf, 0, MAX_SOCK_BUFFER);
    iErr = 0;

    if ((iBuf == 1) && (iEnd1 != 0))  // Copy the contents of buf 1.
    {
    if (MAX_SOCK_BUFFER >= (iEnd1 - iBeg1))  // Copy all the bytes.
    {
    memcpy(szOutBuf, szBuf1 + iBeg1, iEnd1 - iBeg1);
    iErr = iEnd1 - iBeg1;
    iBeg1 = iEnd1 = 0;
    iBuf = 2;
    }
    else  // Only copy the requested number.
    {
    memcpy(szOutBuf, szBuf1 + iBeg1, MAX_SOCK_BUFFER);
    iErr = MAX_SOCK_BUFFER;    // This many bytes sent back.
    iBeg1 += MAX_SOCK_BUFFER;  // Advance to this location.
    }
    }      
    else if ((iBuf == 2) && (iEnd2 != 0))  // Copy the contents of buf 2.
    {
    if (MAX_SOCK_BUFFER >= (iEnd2 - iBeg2))
    {
    memcpy(szOutBuf, szBuf2 + iBeg2, iEnd2 - iBeg2);
    iErr = iEnd2 - iBeg2;
    iBeg2 = iEnd2 = 0;
    iBuf = 1;
    }
    else
    {
    memcpy(szOutBuf, szBuf2 + iBeg2, MAX_SOCK_BUFFER);
    iErr = MAX_SOCK_BUFFER;
    iBeg1 += MAX_SOCK_BUFFER;
    }
    }      
    else
    {
    FD_ZERO(&fdsSocks);
    FD_SET(iSock, &fdsSocks);
    stTimeout.tv_sec = ulTimeout;
    iErr = select(1, &fdsSocks, 0, 0, &stTimeout);
    if (iErr < 1) // Error occured.
    {
    return -1;
    }
    iErr = recv(iSock, szOutBuf, MAX_SOCK_BUFFER, 0);
    szOutBuf[iErr] = '\0';
    if (iErr == 0) return -1;
    }
    }
    }
    return iErr;
    }
      

  5.   

    while( (iIndex = WSAWaitForMultipleEvents(1,eventList,
    false,1000,true)) == WSA_WAIT_FAILED)
    这个地方的1000本来是这个WSA_INFINITE  但是每次都是堵塞在这里  所以我就换了1000, 然后进去以后iIndex是258  可是数组只有1个元素。。
      

  6.   

    在非阻塞模式下 利用 socket 事件 的消息机制, Server 端与 Client 端之间的通信处于异步状态下。 
      通常需要从 CSocket 类派生一个新类,派生新类的目的是重载 socket 事件 的消息函数,然后在 socket 事件 的消息函数中添入合适的代码以完成 Client 端与 Server 端之间的通信,与阻塞模式相比,非阻塞模式无需创建一个新线程。 
      这里将讨论当 Server 端 socket 事件 - FD_ACCEPT 被触发后,该事件的处理函数 OnAccept 是如何进一步被触发的。其它事件的处理函数如 OnConnect, OnReceive 等的触发方式与此类似。 
    在 1 中已提到 Client/Server 端通信时, Server 端 socket 正在接收来自 Client 端 socket 连接请求,这将会触发 FD_ACCEPT 事件,同时 Server 端的 网络传输服务进程 向 Server 端的 socket window (CSocketWnd )发送事件通知消息 WM_SOCKET_NOTIFY , 通知有 FD_ACCEPT 事件产生 , CsocketWnd 在收到事件通知消息后,调用消息处理函数 OnSocketNotify
    LRESULT CSocketWnd::OnSocketNotify(WPARAM wParam, LPARAM lParam) 

    CSocket::AuxQueueAdd(WM_SOCKET_NOTIFY, wParam, lParam); 
    CSocket::ProcessAuxQueue(); 
    return 0L ; 
    }  消息参数 wParam 是 socket 的句柄, lParam 是 socket 事件 。这里稍作解释一下,CSocketWnd 类是作为 CSocket 类的 友元类 ,这意味着它可以访问 CSocket 类中的保护和私有成员函数和变量, AuxQueueAdd 和 ProcessAuxQueue 是 CSocket 类的静态成员函数,如果你对友元不熟悉,请迅速找本有关 C++ 书看一下友元的使用方法吧! 
    ProcessAuxQueue 是实质处理 socket 事件的函数,在该函数中有这样一句代码: CAsyncSocket* pSocket = CAsyncSocket::LookupHandle((SOCKET)wParam, TRUE); 
      其实也就是由 socket 句柄得到发送事件通知消息的 socket 指针 pSocket:从 m_pmapSocketHandle 中查找(见 1 )! 
      最后, WSAGETSELECTEVENT(lParam) 会取出事件类型,在一个简单的 switch 语句中判断事件类型并调用事件处理函数。在这里,事件类型是 FD_ACCEPT ,当然就调用 pSocket->OnAccept ! 
      

  7.   

    http://www.codeguru.com/Cpp/I-N/network/messaging/article.php/c5453 
    采用 CSocket 类编写的基于 Client/Server 的网络聊天程序,它是基于非阻塞模式的Client/Server
    端网络程序典型示例
      

  8.   

    我是自己写的类库  不能用MFC类的  也没有窗口  像上边那样写处理消息行不行呢?
      

  9.   

    对于许多初学者来说,网络通信程序的开发,普遍的一个现象就是觉得难以入手。许多概念,诸如:同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)等,初学者往往迷惑不清,只知其所以而不知起所以然。 
         同步方式指的是发送方不等接收方响应,便接着发下个数据包的通信方式;而异步指发送方发出数据后,等收到接收方发回的响应,才发下一个数据包的通信方式。 
          阻塞套接字是指执行此套接字的网络调用时,直到成功才返回,否则一直阻塞在此网络调用上,比如调用recv()函数读取网络缓冲区中的数据,如果没有数据到达,将一直挂在recv()这个函数调用上,直到读到一些数据,此函数调用才返回;而非阻塞套接字是指执行此套接字的网络调用时,不管是否执行成功,都立即返回。比如调用recv()函数读取网络缓冲区中数据,不管是否读到数据都立即返回,而不会一直挂在此函数调用上。在实际Windows网络通信软件开发中,异步非阻塞套接字是用的最多的。平常所说的C/S(客户端/服务器)结构的软件就是异步非阻塞模式的。 
           对于这些概念,初学者的理解也许只能似是而非,我将用一个最简单的例子说明异步非阻塞Socket的基本原理和工作机制。目的是让初学者不仅对Socket异步非阻塞的概念有个非常透彻的理解,而且也给他们提供一个用Socket开发网络通信应用程序的快速入门方法。操作系统是Windows 98(或NT4.0),开发工具是Visual C++6.0。 
           MFC提供了一个异步类CAsyncSocket,它封装了异步、非阻塞Socket的基本功能,用它做常用的网络通信软件很方便。但它屏蔽了Socket的异步、非阻塞等概念,开发人员无需了解异步、非阻塞Socket的原理和工作机制。因此,建议初学者学习编网络通信程序时,暂且不要用MFC提供的类,而先用Winsock2  API,这样有助于对异步、非阻塞Socket编程机制的理解。 
           为了简单起见,服务器端和客户端的应用程序均是基于MFC的标准对话框,网络通信部分基于Winsock2 API实现。 
           先做服务器端应用程序。 
           用MFC向导做一个基于对话框的应用程序SocketSever,注意第三步中不要选上Windwos Sockets选项。在做好工程后,创建一个SeverSock,将它设置为异步非阻塞模式,并为它注册各种网络异步事件,然后与自定义的网络异步事件联系上,最后还要将它设置为监听模式。在自定义的网络异步事件的回调函数中,你可以得到各种网络异步事件,根据它们的类型,做不同的处理。下面将详细介绍如何编写相关代码。 
           在SocketSeverDlg.h文件的类定义之前增加如下定义: 
          #define  NETWORK_EVENT  WM_USER+166  file://定义网络事件 
         
           SOCKET ServerSock; file://服务器端Socket 
          在类定义中增加如下定义: 
          class CSocketSeverDlg : CDialog 
         { 
                     … 
          public: 
             SOCKET ClientSock[CLNT_MAX_NUM]; file://存储与客户端通信的Socket的数组          /*各种网络异步事件的处理函数*/ 
           void OnClose(SOCKET CurSock);   file://对端Socket断开 
            void OnSend(SOCKET CurSock);   file://发送网络数据包 
           void OnReceive(SOCKET CurSock); file://网络数据包到达 
           void OnAccept(SOCKET CurSock);  file://客户端连接请求         BOOL InitNetwork();  file://初始化网络函数 
             void OnNetEvent(WPARAM wParam, LPARAM lParam); file://异步事件回调函数 
                    … 
         }; 
      

  10.   

    http://www.zjol.com.cn/gb/node2/node195/node56935/node56938/userobject7ai23757.html
      

  11.   

    unsigned long j=1;
    ioctlsocket(sock,FIONBIO,&j);//非阻塞
      

  12.   

    用ioctlsocket函数设置FIONBIO选项。