客户端测试的时候,要尽可能显示服务端的iocp特性。

解决方案 »

  1.   

    #include <stdio.h>
    #include <winsock2.h>
    #include <stdlib.h>
    #pragma comment (lib,"WS2_32.lib")#define SERV_TCP_PORT 9999
    #define DATA_BUFSIZE 1024struct _OVERLAPPELUS
    {
        SOCKET      socket;                    
        char        InBuffer[DATA_BUFSIZE];   // 输入
        OVERLAPPED  ovIn;         
        int         nOutBufIndex;       
        char        OutBuffer[DATA_BUFSIZE];  // 输出
        OVERLAPPED  ovOut;
        DWORD       dwWritten;
    }OVERLAPPELUS, *LPOVERLAPPELUS;_OVERLAPPELUS pKey;HANDLE ghCompletionPort;void CreateWorkerThreads();
    DWORD WINAPI WorkerThread(LPVOID pvoid);
    void IssueRead(struct _OVERLAPPELUS *pCntx);
    void CheckOsVersion();
    void FatalError(char *s);
    void SendString(char *p,struct _OVERLAPPELUS *pCntx);///////////////////////////////////////////////////////////int main(int argc, char *argv[])
    {
        SOCKET  listener;
        SOCKET  newsocket;
        WSADATA WsaData;
        struct  sockaddr_in serverAddress;
        int     err;    CheckOsVersion();    err = WSAStartup (0x0202, &WsaData);
        if (err == SOCKET_ERROR)
        {
            FatalError("网络初始化失败.");
            return EXIT_FAILURE;
        } if ((listener = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) 

    printf("WSASocket() failed with error %d\n", WSAGetLastError()); 
    return EXIT_FAILURE; 
    }      memset(&serverAddress, 0, sizeof(serverAddress));     
        serverAddress.sin_family      = AF_INET;
        serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);   
        serverAddress.sin_port        = htons(SERV_TCP_PORT);      err = bind(listener, (struct sockaddr *)&serverAddress, sizeof(serverAddress));
        if (err < 0)
    {
            FatalError("bind() 错误-请检查 TCP/IP 是否正确安装?");
    }    ghCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL,0,0);
        if (ghCompletionPort == NULL)
    {
            FatalError("CreateIoCompletionPort() 错误-请检查系统是否是Windows NT version 3.51 或更高版本.");
    }
        CreateWorkerThreads();    listen(listener, 5);
        fprintf(stderr, "I/O Completion Ports 模式:端口 %d\n", SERV_TCP_PORT);
        fprintf(stderr, "Ctrl+C 停止服务器程序\n");
    printf("written by http://www.wantsoft.com\n");
    fprintf(stderr, "开始监听客户端:\n");    // 无限循环,接受并处理新的连接
        while (true)
        {
    if ((newsocket = WSAAccept(listener, NULL, NULL, NULL, 0)) == SOCKET_ERROR) 

    printf("WSAAccept() failed with error %d\n", WSAGetLastError()); 
    return EXIT_FAILURE; 
    }  //建立一个 key 并初始化它.
    pKey.socket = newsocket;
            pKey.ovOut.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); //为写信息包过程设置(事件对象) event .
            pKey.ovOut.hEvent = (HANDLE)((DWORD)pKey.ovOut.hEvent | 0x1);         CreateIoCompletionPort(       //为请求绑定端口
    (HANDLE)newsocket,
    ghCompletionPort,
    (DWORD)&pKey,   
    0 );        IssueRead(&pKey);   // 完成第一次读操作
        }    return 0;
    }void CreateWorkerThreads()
    {
        SYSTEM_INFO  sysinfo;
        DWORD        dwThreadId;
        DWORD        dwThreads;
        DWORD        i;    GetSystemInfo(&sysinfo);
        dwThreads = sysinfo.dwNumberOfProcessors * 2 + 2;
        for (i=0; i<dwThreads; i++)
        {
            HANDLE hThread;
            hThread = CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId);
            CloseHandle(hThread);
        }
    }
    // 每一个工作线程从这里开始.
    DWORD WINAPI WorkerThread(LPVOID pVoid)
    {
        BOOL    bResult;
        DWORD   dwNumRead;
        struct _OVERLAPPELUS *pCntx;
        LPOVERLAPPED lpOverlapped = NULL;    UNREFERENCED_PARAMETER(pVoid);    // 无限循环从 I/O completion port 获取信息.
        while (true)
        {
            bResult = GetQueuedCompletionStatus(ghCompletionPort, &dwNumRead, (DWORD*)&pCntx, &lpOverlapped, INFINITE);        if (bResult == FALSE && lpOverlapped == NULL)
            {
                FatalError("WorkerThread - GetQueuedCompletionStatus()错误.\n");
            }
            else if (bResult == FALSE && lpOverlapped != NULL)
            {
    fprintf(stderr,"用户非正常退出.\n"); 
            }
            else if (dwNumRead == 0)
            {    
    fprintf(stderr, "用户已经退出.\n");
                fprintf(stderr, "------------------.\n");
            }
            else
            {
    printf("recv data from client: %s\n", pCntx->InBuffer);
    SendString(pCntx->InBuffer, pCntx);
                IssueRead(pCntx);
            }
        }
    ExitThread(0);
        return 0;
    }
    ///////////////////////////////////////////////////////
    //调用 WSARecv 开始一个异步请求重复获取我们的句柄状态//
    ///////////////////////////////////////////////////////
    void IssueRead(struct _OVERLAPPELUS *pCntx)
    {
    DWORD RecvBytes;
    DWORD Flags =0;
    WSABUF DataBuff;  if (pCntx == NULL)
    return;
    memset(pCntx->InBuffer, 0, sizeof(pCntx->InBuffer));
        ZeroMemory( &(pCntx->ovIn), sizeof(OVERLAPPED)); DataBuff.len = DATA_BUFSIZE; 
    DataBuff.buf = pCntx->InBuffer;  if (WSARecv(pCntx->socket, &DataBuff, 1, &RecvBytes, &Flags, 
    &(pCntx->ovIn), NULL) == SOCKET_ERROR) 

    if (WSAGetLastError() != ERROR_IO_PENDING) 

    printf("WSARecv() failed with error %d\n", WSAGetLastError()); 
    return ; 

    }       
    }// 确保我们运行在正确的版本下 Windows NT (3.51, 4.0, or later)
    void CheckOsVersion()
    {
        OSVERSIONINFO   ver;
        BOOL            bResult;    ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);    bResult = GetVersionEx((LPOSVERSIONINFO) &ver);    if ( (!bResult) ||
             (ver.dwPlatformId != VER_PLATFORM_WIN32_NT) )
        {
            FatalError("ECHOSRV requires Windows NT 3.51 or later.");
        }
    }
    //发送字符串子程序
    void SendString(char *p, struct _OVERLAPPELUS *pCntx)
    {          
    DWORD SendBytes;
    WSABUF DataBuff;
    int len;    strcpy(pCntx->OutBuffer,p);           
    len = strlen(pCntx->OutBuffer); pCntx->OutBuffer[len] = '\0';           
    pCntx->nOutBufIndex = strlen(pCntx->OutBuffer);

    DataBuff.len = len;
    DataBuff.buf = pCntx->OutBuffer;


    if (WSASend(pCntx->socket, &DataBuff, 1, &SendBytes, 0, 
    &(pCntx->ovOut), NULL) == SOCKET_ERROR) 

    if (WSAGetLastError() != ERROR_IO_PENDING) 

    printf("WSASend() failed with error %d\n", WSAGetLastError()); 
    return ; 


    }// 错误句柄
    void FatalError(char *s)
    {
        fprintf(stdout, "%s\n", s);
        exit(EXIT_FAILURE);
    }
      

  2.   

    http://www.codeproject.com/info/search.aspx?artkw=iocp
      

  3.   

    Windows网络与通信程序设计(源码)
    http://download.csdn.net/source/192329其中就有IOCP相关的demo。lz可以参考书籍一起看,效果更好些
      

  4.   

    代码网上很多的,搜下就有。
    你可以用NetAssist(网络调试助手),帮你测试。并发的发送和接收大流量的数据
      

  5.   

    http://topic.csdn.net/u/20100715/14/76aa6ed0-b964-429d-b3a4-fad472d69d92.html?91138
    我帖子的地址,里面有我前面上传的服务器源码,还有个客户端测试程序,可搜索我上传的资源
      

  6.   

    http://www.codeproject.com/KB/IP/iocp_server_client.aspx