IO完成端口学习示例

来源:互联网 发布:离散最优化问题 编辑:程序博客网 时间:2024/05/16 11:43
http://blog.csdn.net/jaff20071234/article/details/6538357
分类: windows编程 315人阅读 评论(0) 收藏 举报
iosocketnullthreadreferencedll

连接:

http://blog.csdn.net/sodme/archive/2006/04/17/666062.aspx

http://lijinshui.bokee.com/3245440.html

http://blog.csdn.net/sodme/archive/2005/07/17/427405.aspx

http://blog.csdn.net/vieri_ch/archive/2005/10/11/499357.aspx

http://blog.csdn.net/SeaWave/archive/2006/05/21/747863.aspx

http://blog.csdn.net/xuwei2007/archive/2007/08/29/1764332.aspx

http://blog.csdn.net/juestSoftware/archive/2008/09/14/2855625.aspx

http://blog.csdn.net/wangandy7811/archive/2009/12/04/4930897.aspx

 

个人总结:

学习完成端口时,采用完成端口编写的服务器示例:

[css] view plaincopy
  1. // CompletionPortServer.cpp : 定义控制台应用程序的入口点。  
  2. //  
  3. #includ"stdafx.h"  
  4. #include <WinSock2.h>  
  5. #include <windows.h>  
  6. #include <process.h>  
  7. #pragma comment(lib, "ws2_32")  
  8. #define  DATA_BUFSIZE   10  
  9. #define  RECV_POSTED    0  
  10. #define  SEND_POSTED    1  
  11. typedef struct _PER_HANDLE_DATA   
  12. {  
  13.     SOCKET          Socket;  
  14.     SOCKADDR_STORAGE  ClientAddr;  
  15.     // Other information useful to be associated with the handle  
  16. } PER_HANDLE_DATA, * LPPER_HANDLE_DATA;  
  17. typedef struct  
  18. {  
  19.     OVERLAPPED Overlapped;  
  20.     WSABUF      DataBuf;  
  21.     char       Buffer[DATA_BUFSIZE];  
  22.     int            BufferLen;  
  23.     int        OperationType;  
  24. } PER_IO_DATA, *LPPER_IO_DATA;  
  25. int StartWinsock( )  
  26. {  
  27.     WORD wVersionRequested;  
  28.     WSADATA wsaData;  
  29.     int err;  
  30.     wVersionRequested = MAKEWORD( 22 );  
  31.     err = WSAStartup( wVersionRequested, &wsaData );  
  32.     if ( err != 0 ) {  
  33.         /* Tell the user that we could not find a usable */  
  34.         /* WinSock DLL.                                  */  
  35.         printf("error = %d/n", WSAGetLastError());  
  36.         return 0;  
  37.     }  
  38.     /* Confirm that the WinSock DLL supports 2.2.*/  
  39.     /* Note that if the DLL supports versions greater    */  
  40.     /* than 2.2 in addition to 2.2, it will still return */  
  41.     /* 2.2 in wVersion since that is the version we      */  
  42.     /* requested.                                        */  
  43.     if ( LOBYTE( wsaData.wVersion ) != 2 ||  
  44.         HIBYTE( wsaData.wVersion ) != 2 ) {  
  45.             /* Tell the user that we could not find a usable */  
  46.             /* WinSock DLL.                                  */  
  47.             WSACleanup( );  
  48.             return 0;   
  49.     }  
  50.     printf("max socket is :%d/n", wsaData.iMaxSockets);  
  51.     return 1;  
  52. }  
  53. unsigned int  WINAPI __stdcall ServerWorkerThread(LPVOID CompletionPortID)  
  54. {  
  55.     // The requirements for the worker thread will be   
  56.     // discussed later.  
  57.     HANDLE CompletionPort = (HANDLE) CompletionPortID;  
  58.     DWORD BytesTransferred;  
  59.     LPPER_HANDLE_DATA PerHandleData;  
  60.     LPPER_IO_DATA PerIoData;  
  61.     DWORD SendBytes, RecvBytes;  
  62.     DWORD Flags;  
  63.     int iRet = 0;  
  64.     while(1)  
  65.     {  
  66.         // Wait for I/O to complete on any socket  
  67.         // associated with the completion port  
  68.         iRet = GetQueuedCompletionStatus(CompletionPort,  
  69.             &BytesTransferred,(LPDWORD)&PerHandleData,  
  70.             (LPOVERLAPPED *) &PerIoData, INFINITE);  
  71.         // First check to see if an error has occurred  
  72.         // on the socket; if so, close the   
  73.         // socket and clean up the per-handle data  
  74.         // and per-I/O operation data associated with  
  75.         // the socket  
  76.         if ( BytesTransferred == 0 &&  
  77.             (PerIoData->OperationType == RECV_POSTED  || PerIoData->OperationType == SEND_POSTED) )  
  78.         {  
  79.             // A zero BytesTransferred indicates that the  
  80.             // socket has been closed by the peer, so  
  81.             // you should close the socket. Note:   
  82.             // Per-handle data was used to reference the  
  83.             // socket associated with the I/O operation.  
  84.             closesocket(PerHandleData->Socket);  
  85.             GlobalFree(PerHandleData);  
  86.             GlobalFree(PerIoData);  
  87.             continue;  
  88.         }  
  89.         if (iRet == 0)  
  90.         {  
  91.             closesocket(PerHandleData->Socket);  
  92.             GlobalFree(PerHandleData);  
  93.             GlobalFree(PerIoData);  
  94.             continue;  
  95.         }  
  96.         if (BytesTransferred == -10)  
  97.         {  
  98.             // A zero BytesTransferred indicates that the  
  99.             // socket has been closed by the peer, so  
  100.             // you should close the socket. Note:   
  101.             // Per-handle data was used to reference the  
  102.             // socket associated with the I/O operation.  
  103.             closesocket(PerHandleData->Socket);  
  104.             GlobalFree(PerHandleData);  
  105.             GlobalFree(PerIoData);  
  106.             continue;  
  107.         }  
  108.         // Service the completed I/O request. You can  
  109.         // determine which I/O request has just  
  110.         // completed by looking at the OperationType  
  111.         // field contained in the per-I/O operation data.  
  112.         if (PerIoData->OperationType == RECV_POSTED)  
  113.         {  
  114.             // Do something with the received data  
  115.             // in PerIoData->Buffer  
  116.             printf("%s/n",PerIoData->Buffer);  
  117.               
  118.             //Response:  
  119.             // Set up the per-I/O operation data for the next  
  120.             // overlapped call  
  121.             ZeroMemory(&(PerIoData->Overlapped),  
  122.                 sizeof(OVERLAPPED));  
  123.               
  124.             PerIoData->DataBuf.len = DATA_BUFSIZE;  
  125.             PerIoData->DataBuf.buf = PerIoData->Buffer;  
  126.             PerIoData->OperationType = SEND_POSTED;  
  127.             memset(PerIoData->Buffer, 0, DATA_BUFSIZE);  
  128.             strcpy_s(PerIoData->Buffer, DATA_BUFSIZE, "OK");  
  129.             //SendBytes = DATA_BUFSIZE;  
  130.             Flags = 0;  
  131.             iRet = WSASend(PerHandleData->Socket,   
  132.                 &(PerIoData->DataBuf), 1, &SendBytes,  
  133.                 Flags, &(PerIoData->Overlapped), NULL);  
  134.             if (iRet == SOCKET_ERROR)  
  135.             {  
  136.                 if (WSAGetLastError() != WSA_IO_PENDING)  
  137.                 {  
  138.                     PostQueuedCompletionStatus(CompletionPort, -20, reinterpret_cast<DWORD> ((LPPER_HANDLE_DATA)&PerHandleData),  
  139.                         (LPOVERLAPPED ) &PerIoData);  
  140.                 }  
  141.             }  
  142.             printf("%d bytes data is sent /n", SendBytes);  
  143.         }  
  144.         else if (PerIoData->OperationType == SEND_POSTED)  
  145.         {  
  146.             // Post another WSASend or WSARecv operation.  
  147.             // As an example, we will post another WSARecv()  
  148.             // I/O operation.  
  149.             Flags = 0;  
  150.             // Set up the per-I/O operation data for the next  
  151.             // overlapped call  
  152.             ZeroMemory(&(PerIoData->Overlapped),  
  153.                 sizeof(OVERLAPPED));  
  154.             PerIoData->DataBuf.len = DATA_BUFSIZE;  
  155.             PerIoData->DataBuf.buf = PerIoData->Buffer;  
  156.             PerIoData->OperationType = RECV_POSTED;  
  157.             iRet = WSARecv(PerHandleData->Socket,   
  158.                 &(PerIoData->DataBuf), 1, &RecvBytes,  
  159.                 &Flags, &(PerIoData->Overlapped), NULL);  
  160.             if (iRet == SOCKET_ERROR)  
  161.             {  
  162.                 if (WSAGetLastError() != WSA_IO_PENDING)  
  163.                 {  
  164.                     PostQueuedCompletionStatus(CompletionPort, -10, reinterpret_cast<DWORD>((LPPER_HANDLE_DATA)&PerHandleData),  
  165.                         (LPOVERLAPPED ) &PerIoData);  
  166.                 }  
  167.             }  
  168.         }  
  169.     }  
  170. }  
  171. int _tmain()  
  172. {  
  173.     SYSTEM_INFO stSysInfo;  
  174.     memset(&stSysInfo, 0, sizeof(stSysInfo));     
  175.     SOCKADDR_IN InternetAddr;  
  176.     SOCKET Listen;  
  177.     DWORD RecvBytes;  
  178.     DWORD Flags = 0;  
  179.     // Load Winsock  
  180.     int iResult = StartWinsock();  
  181.     if ( iResult == 0 )  
  182.     {  
  183.         printf("winsock start up failed./n, error = %d/n", WSAGetLastError());  
  184.     }  
  185.     // Create an I/O completion port  
  186.     // only processor's number thread is running by default.  
  187.     HANDLE hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 00);  
  188.     // Determine how many processors are on the system  
  189.     GetSystemInfo(&stSysInfo);  
  190.     unsigned int i ;  
  191.     for(i = 0; i < stSysInfo.dwNumberOfProcessors; i++)  
  192.     {  
  193.         HANDLE ThreadHandle;  
  194.         // Create a server worker thread, and pass the  
  195.         // completion port to the thread. NOTE: the  
  196.         // ServerWorkerThread procedure is not defined  
  197.         // in this listing.  
  198.         ThreadHandle =(HANDLE) _beginthreadex(NULL, 0, ServerWorkerThread, hCompletionPort, 0, NULL);  
  199.           
  200.         // Close the thread handle  
  201.         CloseHandle(ThreadHandle);  
  202.     }  
  203.     // Create a listening socket  
  204.     Listen = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0,  
  205.         WSA_FLAG_OVERLAPPED);  
  206.     int on = 1;  
  207.     setsockopt(Listen, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));  
  208.     InternetAddr.sin_family = AF_INET;  
  209.     InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);  
  210.     InternetAddr.sin_port = htons(5150);   
  211.     bind(Listen, (PSOCKADDR) &InternetAddr,  
  212.         sizeof(InternetAddr));  
  213.     // Prepare socket for listening  
  214.     listen(Listen, 5);  
  215.     while(1)  
  216.     {  
  217.         PER_HANDLE_DATA *PerHandleData=NULL;  
  218.         PER_IO_DATA *PerIoData = NULL;  
  219.         SOCKADDR_IN saRemote;  
  220.         SOCKET Accept;  
  221.         int RemoteLen;  
  222.         // Step 5:  
  223.         // Accept connections and assign to the completion  
  224.         // port  
  225.         RemoteLen = sizeof(saRemote);  
  226.         Accept = WSAAccept(Listen, (SOCKADDR *)&saRemote,   
  227.             &RemoteLen, NULL, NULL);  
  228.         // Step 6:  
  229.         // Create per-handle data information structure to   
  230.         // associate with the socket  
  231.         PerHandleData = (LPPER_HANDLE_DATA)   
  232.             GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA));  
  233.         PerIoData = (LPPER_IO_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_DATA));  
  234.         printf("Socket number %d connected/n", Accept);  
  235.         PerHandleData->Socket = Accept;  
  236.         memcpy(&PerHandleData->ClientAddr, &saRemote, RemoteLen);  
  237.         // Step 7:  
  238.         // Associate the accepted socket with the  
  239.         // completion port  
  240.         CreateIoCompletionPort((HANDLE) Accept,  
  241.             hCompletionPort, reinterpret_cast<DWORD>(PerHandleData), 0);  
  242.         // Set up the per-I/O operation data for the next  
  243.         // overlapped call  
  244.         ZeroMemory(&(PerIoData->Overlapped),  
  245.             sizeof(OVERLAPPED));  
  246.         PerIoData->DataBuf.len = DATA_BUFSIZE;  
  247.         PerIoData->DataBuf.buf = PerIoData->Buffer;  
  248.         PerIoData->OperationType = RECV_POSTED;  
  249.         if (WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,   
  250.             &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)   
  251.         {   
  252.             if (WSAGetLastError() != ERROR_IO_PENDING)   
  253.             {   
  254.                 printf("WSARecv() failed with error %d/n", WSAGetLastError());   
  255.                 return 0;   
  256.             }   
  257.         }   
  258.     }  
  259.     return 0;  
  260. }  
 

客户端代码:

[cpp] view plaincopy
  1. // ClientTest.cpp : 定义控制台应用程序的入口点。  
  2. //  
  3. #include "stdafx.h"  
  4. #include <winsock2.h>  
  5. #include <process.h>  
  6. #pragma comment(lib, "ws2_32")  
  7. #define  BUFSIZE        10  
  8. int StartWinsock( )  
  9. {  
  10.     WORD wVersionRequested;  
  11.     WSADATA wsaData;  
  12.     int err;  
  13.     wVersionRequested = MAKEWORD( 2, 2 );  
  14.     err = WSAStartup( wVersionRequested, &wsaData );  
  15.     if ( err != 0 ) {  
  16.         /* Tell the user that we could not find a usable */  
  17.         /* WinSock DLL.                                  */  
  18.         printf("error = %d/n", WSAGetLastError());  
  19.         return 0;  
  20.     }  
  21.     /* Confirm that the WinSock DLL supports 2.2.*/  
  22.     /* Note that if the DLL supports versions greater    */  
  23.     /* than 2.2 in addition to 2.2, it will still return */  
  24.     /* 2.2 in wVersion since that is the version we      */  
  25.     /* requested.                                        */  
  26.     if ( LOBYTE( wsaData.wVersion ) != 2 ||  
  27.         HIBYTE( wsaData.wVersion ) != 2 ) {  
  28.             /* Tell the user that we could not find a usable */  
  29.             /* WinSock DLL.                                  */  
  30.             WSACleanup( );  
  31.             return 0;   
  32.     }  
  33.     printf("max socket is :%d/n", wsaData.iMaxSockets);  
  34.     return 1;  
  35. }  
  36. int count = 0;  
  37. unsigned __stdcall WorkerThread(LPVOID pSock)  
  38. {  
  39.     SOCKET clientSock = reinterpret_cast<SOCKET>(pSock);  
  40.     int iResult = 0;  
  41.     char buf[BUFSIZE];  
  42.     int i = 0;  
  43.     while ( i < 10 )  
  44.     {  
  45.         ZeroMemory(buf, BUFSIZE);  
  46.         memset(buf, 'E', BUFSIZE -1);  
  47.         //strcpy_s(buf, BUFSIZE, "1234567890");  
  48.         iResult = send(clientSock, buf, BUFSIZE, 0);  
  49.         if ( iResult == SOCKET_ERROR )  
  50.         {  
  51.             printf("%d个客户 send error = %d/n",count, WSAGetLastError());  
  52.         }  
  53.         ZeroMemory(buf, BUFSIZE);  
  54.         iResult = recv(clientSock, buf, BUFSIZE, 0);  
  55.         if ( iResult == SOCKET_ERROR )  
  56.         {  
  57.             printf("%d个客户 recv error = %d/n", count, WSAGetLastError());  
  58.             continue;  
  59.         }  
  60.         printf("received data is :%s/n", buf);  
  61.         i++;  
  62.         Sleep(2000);  
  63.     }  
  64.     iResult = shutdown(clientSock, SD_BOTH);  
  65.     if ( SOCKET_ERROR == iResult )  
  66.     {  
  67.         printf("%d个客户 shutdown error = %d/n", count, WSAGetLastError());  
  68.     }  
  69.     iResult = closesocket(clientSock);  
  70.     if ( SOCKET_ERROR == iResult )  
  71.     {  
  72.         printf("%d个客户 closesocket error = %d/n", count, WSAGetLastError());  
  73.     }  
  74.     return 0;  
  75. }  
  76. int _tmain(int argc, _TCHAR* argv[])  
  77. {  
  78.     int iResult = StartWinsock();  
  79.     struct sockaddr_in serverAddr;  
  80.     memset(&serverAddr, 0 ,sizeof(serverAddr));  
  81.     serverAddr.sin_family = AF_INET;  
  82.     serverAddr.sin_port = htons(5150);  
  83.     serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");  
  84.     while (1)  
  85.     {  
  86.         count++;  
  87.         printf("第%d个socket连接",count);  
  88.         SOCKET clientSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  
  89.         if ( clientSock ==INVALID_SOCKET  )  
  90.         {  
  91.             printf("socket error = %d/n", WSAGetLastError());  
  92.         }  
  93.         iResult = connect(clientSock, (const sockaddr *)&serverAddr, sizeof(serverAddr));  
  94.         if ( iResult == SOCKET_ERROR )  
  95.         {  
  96.             printf("connect error = %d/n",WSAGetLastError());  
  97.             closesocket(clientSock);  
  98.             continue;  
  99.         }  
  100.         _beginthreadex(NULL, 0, WorkerThread, (LPVOID)clientSock, 0, NULL);  
  101.           
  102.         Sleep(5000);  
  103.     }  
  104.     WSACleanup();  
  105.     return 0;  
  106. }  
 

 

可能存在一些资源未清理的情况,仅仅是做一个练习。

0 0