windows网络编程

 

       select模式有端口数限制,FD_SIZE被定义为64,如果不去修改这个系统定义的宏,这FD_SET结构里面最多只能存64个端口。

我把它改成1000试过,可以接收1000个端口,不知道这样子会不会有什么问题。

windows 网络编程 8章 Winsock I/O方法

 

select模型

 

  1. // Module Name: select.cpp   

  2. //   

  3. // Description:   

  4. //   

  5. //    This sample illustrates how to develop a simple echo server Winsock   

  6. //    application using the select() API I/O model. This sample is   

  7. //    implemented as a console-style application and simply prints   

  8. //    messages when connections are established and removed from the server.   

  9. //    The application listens for TCP connections on port 5150 and accepts   

  10. //    them as they arrive. When this application receives data from a client,   

  11. //    it simply echos (this is why we call it an echo server) the data back in   

  12. //    it's original form until the client closes the connection.   

  13. //   

  14. // Compile:   

  15. //   

  16. //    cl -o select select.cpp ws2_32.lib   

  17. //   

  18. // Command Line Options:   

  19. //   

  20. //    select.exe    

  21. //   

  22. //    Note: There are no command line options for this sample.   

  23. //   

  24. #include <winsock2.h>   

  25. #include <windows.h>   

  26. #include <stdio.h>   

  27.   

  28. #define PORT 5150   

  29. #define DATA_BUFSIZE 8192   

  30.   

  31. typedef struct _SOCKET_INFORMATION {   

  32.    CHAR Buffer[DATA_BUFSIZE];   

  33.    WSABUF DataBuf;   

  34.    SOCKET Socket;   

  35.    OVERLAPPED Overlapped;   

  36.    DWORD BytesSEND;   

  37.    DWORD BytesRECV;   

  38. } SOCKET_INFORMATION, * LPSOCKET_INFORMATION;   

  39.   

  40. BOOL CreateSocketInformation(SOCKET s);   

  41. void FreeSocketInformation(DWORD Index);   

  42.   

  43. DWORD TotalSockets = 0;   

  44. LPSOCKET_INFORMATION SocketArray[FD_SETSIZE];   

  45.   

  46. void main(void)   

  47. {   

  48.    SOCKET ListenSocket;   

  49.    SOCKET AcceptSocket;   

  50.    SOCKADDR_IN InternetAddr;   

  51.    WSADATA wsaData;   

  52.    INT Ret;   

  53.    FD_SET WriteSet;   

  54.    FD_SET ReadSet;   

  55.    DWORD i;   

  56.    DWORD Total;   

  57.    ULONG NonBlock;   

  58.    DWORD Flags;   

  59.    DWORD SendBytes;   

  60.    DWORD RecvBytes;   

  61.   

  62.   

  63.    if ((Ret = WSAStartup(0x0202,&wsaData)) != 0)   

  64.    {   

  65.       printf("WSAStartup() failed with error %d/n", Ret);   

  66.       WSACleanup();   

  67.       return;   

  68.    }   

  69.   

  70.    // Prepare a socket to listen for connections.   

  71.   

  72.    if ((ListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,   

  73.       WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)    

  74.    {   

  75.       printf("WSASocket() failed with error %d/n", WSAGetLastError());   

  76.       return;   

  77.    }   

  78.   

  79.    InternetAddr.sin_family = AF_INET;   

  80.    InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);   

  81.    InternetAddr.sin_port = htons(PORT);   

  82.   

  83.    if (bind(ListenSocket, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr))   

  84.       == SOCKET_ERROR)   

  85.    {   

  86.       printf("bind() failed with error %d/n", WSAGetLastError());   

  87.       return;   

  88.    }   

  89.   

  90.    if (listen(ListenSocket, 5))   

  91.    {   

  92.       printf("listen() failed with error %d/n", WSAGetLastError());   

  93.       return;   

  94.    }   

  95.   

  96.    // Change the socket mode on the listening socket from blocking to   

  97.    // non-block so the application will not block waiting for requests.   

  98.   

  99.    NonBlock = 1;   

  100.    if (ioctlsocket(ListenSocket, FIONBIO, &NonBlock) == SOCKET_ERROR)   

  101.    {   

  102.       printf("ioctlsocket() failed with error %d/n", WSAGetLastError());   

  103.       return;   

  104.    }   

  105.   

  106.    while(TRUE)   

  107.    {   

  108.       // Prepare the Read and Write socket sets for network I/O notification.   

  109.       FD_ZERO(&ReadSet);   

  110.       FD_ZERO(&WriteSet);   

  111.   

  112.       // Always look for connection attempts.   

  113.   

  114.       FD_SET(ListenSocket, &ReadSet);   

  115.   

  116.       // Set Read and Write notification for each socket based on the   

  117.       // current state the buffer.  If there is data remaining in the   

  118.       // buffer then set the Write set otherwise the Read set.   

  119.   

  120.       for (i = 0; i < TotalSockets; i++)   

  121.          if (SocketArray[i]->BytesRECV > SocketArray[i]->BytesSEND)   

  122.             FD_SET(SocketArray[i]->Socket, &WriteSet);   

  123.          else  

  124.             FD_SET(SocketArray[i]->Socket, &ReadSet);   

  125.   

  126.       if ((Total = select(0, &ReadSet, &WriteSet, NULL, NULL)) == SOCKET_ERROR)   

  127.       {   

  128.          printf("select() returned with error %d/n", WSAGetLastError());   

  129.          return;   

  130.       }   

  131.   

  132.       // Check for arriving connections on the listening socket.   

  133.       if (FD_ISSET(ListenSocket, &ReadSet))   

  134.       {   

  135.          Total--;   

  136.          if ((AcceptSocket = accept(ListenSocket, NULL, NULL)) != INVALID_SOCKET)   

  137.          {   

  138.   

  139.             // Set the accepted socket to non-blocking mode so the server will   

  140.             // not get caught in a blocked condition on WSASends   

  141.   

  142.             NonBlock = 1;   

  143.             if (ioctlsocket(AcceptSocket, FIONBIO, &NonBlock) == SOCKET_ERROR)   

  144.             {   

  145.                printf("ioctlsocket() failed with error %d/n", WSAGetLastError());   

  146.                return;   

  147.             }   

  148.   

  149.             if (CreateSocketInformation(AcceptSocket) == FALSE)   

  150.                return;   

  151.   

  152.          }   

  153.          else  

  154.          {         

  155.             if (WSAGetLastError() != WSAEWOULDBLOCK)   

  156.             {   

  157.                printf("accept() failed with error %d/n", WSAGetLastError());   

  158.                return;   

  159.             }   

  160.          }   

  161.       }   

  162.   

  163.       // Check each socket for Read and Write notification until the number   

  164.       // of sockets in Total is satisfied.   

  165.   

  166.       for (i = 0; Total > 0 && i < TotalSockets; i++)   

  167.       {   

  168.          LPSOCKET_INFORMATION SocketInfo = SocketArray[i];   

  169.   

  170.          // If the ReadSet is marked for this socket then this means data   

  171.          // is available to be read on the socket.   

  172.   

  173.          if (FD_ISSET(SocketInfo->Socket, &ReadSet))   

  174.          {   

  175.             Total--;   

  176.   

  177.             SocketInfo->DataBuf.buf = SocketInfo->Buffer;   

  178.             SocketInfo->DataBuf.len = DATA_BUFSIZE;   

  179.   

  180.             Flags = 0;   

  181.             if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes,   

  182.                &Flags, NULL, NULL) == SOCKET_ERROR)   

  183.             {   

  184.                if (WSAGetLastError() != WSAEWOULDBLOCK)   

  185.                {   

  186.                   printf("WSARecv() failed with error %d/n", WSAGetLastError());   

  187.   

  188.                   FreeSocketInformation(i);   

  189.                }   

  190.   

  191.                continue;   

  192.             }    

  193.             else  

  194.             {   

  195.                SocketInfo->BytesRECV = RecvBytes;   

  196.   

  197.                // If zero bytes are received, this indicates the peer closed the   

  198.                // connection.   

  199.                if (RecvBytes == 0)   

  200.                {   

  201.                   FreeSocketInformation(i);   

  202.                   continue;   

  203.                }   

  204.             }   

  205.          }   

  206.   

  207.   

  208.          // If the WriteSet is marked on this socket then this means the internal   

  209.          // data buffers are available for more data.   

  210.   

  211.          if (FD_ISSET(SocketInfo->Socket, &WriteSet))   

  212.          {   

  213.             Total--;   

  214.   

  215.             SocketInfo->DataBuf.buf = SocketInfo->Buffer + SocketInfo->BytesSEND;   

  216.             SocketInfo->DataBuf.len = SocketInfo->BytesRECV - SocketInfo->BytesSEND;   

  217.   

  218.             if (WSASend(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &SendBytes, 0,   

  219.                NULL, NULL) == SOCKET_ERROR)   

  220.             {   

  221.                if (WSAGetLastError() != WSAEWOULDBLOCK)   

  222.                {   

  223.                   printf("WSASend() failed with error %d/n", WSAGetLastError());   

  224.   

  225.                   FreeSocketInformation(i);   

  226.                }   

  227.   

  228.                continue;   

  229.             }   

  230.             else  

  231.             {   

  232.                SocketInfo->BytesSEND += SendBytes;   

  233.   

  234.                if (SocketInfo->BytesSEND == SocketInfo->BytesRECV)   

  235.                {   

  236.                   SocketInfo->BytesSEND = 0;   

  237.                   SocketInfo->BytesRECV = 0;   

  238.                }   

  239.             }   

  240.          }   

  241.       }   

  242.    }   

  243. }   

  244.   

  245. BOOL CreateSocketInformation(SOCKET s)   

  246. {   

  247.    LPSOCKET_INFORMATION SI;   

  248.          

  249.    printf("Accepted socket number %d/n", s);   

  250.   

  251.    if ((SI = (LPSOCKET_INFORMATION) GlobalAlloc(GPTR,   

  252.       sizeof(SOCKET_INFORMATION))) == NULL)   

  253.    {   

  254.       printf("GlobalAlloc() failed with error %d/n", GetLastError());   

  255.       return FALSE;   

  256.    }   

  257.   

  258.    // Prepare SocketInfo structure for use.   

  259.   

  260.    SI->Socket = s;   

  261.    SI->BytesSEND = 0;   

  262.    SI->BytesRECV = 0;   

  263.   

  264.    SocketArray[TotalSockets] = SI;   

  265.   

  266.    TotalSockets++;   

  267.   

  268.    return(TRUE);   

  269. }   

  270.   

  271. void FreeSocketInformation(DWORD Index)   

  272. {   

  273.    LPSOCKET_INFORMATION SI = SocketArray[Index];   

  274.    DWORD i;   

  275.   

  276.    closesocket(SI->Socket);   

  277.   

  278.    printf("Closing socket number %d/n", SI->Socket);   

  279.   

  280.    GlobalFree(SI);   

  281.   

  282.    // Squash the socket array   

  283.   

  284.    for (i = Index; i < TotalSockets; i++)   

  285.    {   

  286.       SocketArray[i] = SocketArray[i + 1];   

  287.    }   

  288.   

  289.    TotalSockets--;   

  290. }  

[cpp]

  1. // Module Name: select.cpp  

  2. //  

  3. // Description:  

  4. //  

  5. //    This sample illustrates how to develop a simple echo server Winsock  

  6. //    application using the select() API I/O model. This sample is  

  7. //    implemented as a console-style application and simply prints  

  8. //    messages when connections are established and removed from the server.  

  9. //    The application listens for TCP connections on port 5150 and accepts  

  10. //    them as they arrive. When this application receives data from a client,  

  11. //    it simply echos (this is why we call it an echo server) the data back in  

  12. //    it's original form until the client closes the connection.  

  13. //  

  14. // Compile:  

  15. //  

  16. //    cl -o select select.cpp ws2_32.lib  

  17. //  

  18. // Command Line Options:  

  19. //  

  20. //    select.exe   

  21. //  

  22. //    Note: There are no command line options for this sample.  

  23. //  

  24. #include <winsock2.h>  

  25. #include <windows.h>  

  26. #include <stdio.h>  

  27.   

  28. #define PORT 5150  

  29. #define DATA_BUFSIZE 8192  

  30.   

  31. typedef struct _SOCKET_INFORMATION {  

  32.    CHAR Buffer[DATA_BUFSIZE];  

  33.    WSABUF DataBuf;  

  34.    SOCKET Socket;  

  35.    OVERLAPPED Overlapped;  

  36.    DWORD BytesSEND;  

  37.    DWORD BytesRECV;  

  38. } SOCKET_INFORMATION, * LPSOCKET_INFORMATION;  

  39.   

  40. BOOL CreateSocketInformation(SOCKET s);  

  41. void FreeSocketInformation(DWORD Index);  

  42.   

  43. DWORD TotalSockets = 0;  

  44. LPSOCKET_INFORMATION SocketArray[FD_SETSIZE];  

  45.   

  46. void main(void)  

  47. {  

  48.    SOCKET ListenSocket;  

  49.    SOCKET AcceptSocket;  

  50.    SOCKADDR_IN InternetAddr;  

  51.    WSADATA wsaData;  

  52.    INT Ret;  

  53.    FD_SET WriteSet;  

  54.    FD_SET ReadSet;  

  55.    DWORD i;  

  56.    DWORD Total;  

  57.    ULONG NonBlock;  

  58.    DWORD Flags;  

  59.    DWORD SendBytes;  

  60.    DWORD RecvBytes;  

  61.   

  62.   

  63.    if ((Ret = WSAStartup(0x0202,&wsaData)) != 0)  

  64.    {  

  65.       printf("WSAStartup() failed with error %d/n", Ret);  

  66.       WSACleanup();  

  67.       return;  

  68.    }  

  69.   

  70.    // Prepare a socket to listen for connections.  

  71.   

  72.    if ((ListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,  

  73.       WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)   

  74.    {  

  75.       printf("WSASocket() failed with error %d/n", WSAGetLastError());  

  76.       return;  

  77.    }  

  78.   

  79.    InternetAddr.sin_family = AF_INET;  

  80.    InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);  

  81.    InternetAddr.sin_port = htons(PORT);  

  82.   

  83.    if (bind(ListenSocket, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr))  

  84.       == SOCKET_ERROR)  

  85.    {  

  86.       printf("bind() failed with error %d/n", WSAGetLastError());  

  87.       return;  

  88.    }  

  89.   

  90.    if (listen(ListenSocket, 5))  

  91.    {  

  92.       printf("listen() failed with error %d/n", WSAGetLastError());  

  93.       return;  

  94.    }  

  95.   

  96.    // Change the socket mode on the listening socket from blocking to  

  97.    // non-block so the application will not block waiting for requests.  

  98.   

  99.    NonBlock = 1;  

  100.    if (ioctlsocket(ListenSocket, FIONBIO, &NonBlock) == SOCKET_ERROR)  

  101.    {  

  102.       printf("ioctlsocket() failed with error %d/n", WSAGetLastError());  

  103.       return;  

  104.    }  

  105.   

  106.    while(TRUE)  

  107.    {  

  108.       // Prepare the Read and Write socket sets for network I/O notification.  

  109.       FD_ZERO(&ReadSet);  

  110.       FD_ZERO(&WriteSet);  

  111.   

  112.       // Always look for connection attempts.  

  113.   

  114.       FD_SET(ListenSocket, &ReadSet);  

  115.   

  116.       // Set Read and Write notification for each socket based on the  

  117.       // current state the buffer.  If there is data remaining in the  

  118.       // buffer then set the Write set otherwise the Read set.  

  119.   

  120.       for (i = 0; i < TotalSockets; i++)  

  121.          if (SocketArray[i]->BytesRECV > SocketArray[i]->BytesSEND)  

  122.             FD_SET(SocketArray[i]->Socket, &WriteSet);  

  123.          else  

  124.             FD_SET(SocketArray[i]->Socket, &ReadSet);  

  125.   

  126.       if ((Total = select(0, &ReadSet, &WriteSet, NULL, NULL)) == SOCKET_ERROR)  

  127.       {  

  128.          printf("select() returned with error %d/n", WSAGetLastError());  

  129.          return;  

  130.       }  

  131.   

  132.       // Check for arriving connections on the listening socket.  

  133.       if (FD_ISSET(ListenSocket, &ReadSet))  

  134.       {  

  135.          Total--;  

  136.          if ((AcceptSocket = accept(ListenSocket, NULL, NULL)) != INVALID_SOCKET)  

  137.          {  

  138.   

  139.             // Set the accepted socket to non-blocking mode so the server will  

  140.             // not get caught in a blocked condition on WSASends  

  141.   

  142.             NonBlock = 1;  

  143.             if (ioctlsocket(AcceptSocket, FIONBIO, &NonBlock) == SOCKET_ERROR)  

  144.             {  

  145.                printf("ioctlsocket() failed with error %d/n", WSAGetLastError());  

  146.                return;  

  147.             }  

  148.   

  149.             if (CreateSocketInformation(AcceptSocket) == FALSE)  

  150.                return;  

  151.   

  152.          }  

  153.          else  

  154.          {        

  155.             if (WSAGetLastError() != WSAEWOULDBLOCK)  

  156.             {  

  157.                printf("accept() failed with error %d/n", WSAGetLastError());  

  158.                return;  

  159.             }  

  160.          }  

  161.       }  

  162.   

  163.       // Check each socket for Read and Write notification until the number  

  164.       // of sockets in Total is satisfied.  

  165.   

  166.       for (i = 0; Total > 0 && i < TotalSockets; i++)  

  167.       {  

  168.          LPSOCKET_INFORMATION SocketInfo = SocketArray[i];  

  169.   

  170.          // If the ReadSet is marked for this socket then this means data  

  171.          // is available to be read on the socket.  

  172.   

  173.          if (FD_ISSET(SocketInfo->Socket, &ReadSet))  

  174.          {  

  175.             Total--;  

  176.   

  177.             SocketInfo->DataBuf.buf = SocketInfo->Buffer;  

  178.             SocketInfo->DataBuf.len = DATA_BUFSIZE;  

  179.   

  180.             Flags = 0;  

  181.             if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes,  

  182.                &Flags, NULL, NULL) == SOCKET_ERROR)  

  183.             {  

  184.                if (WSAGetLastError() != WSAEWOULDBLOCK)  

  185.                {  

  186.                   printf("WSARecv() failed with error %d/n", WSAGetLastError());  

  187.   

  188.                   FreeSocketInformation(i);  

  189.                }  

  190.   

  191.                continue;  

  192.             }   

  193.             else  

  194.             {  

  195.                SocketInfo->BytesRECV = RecvBytes;  

  196.   

  197.                // If zero bytes are received, this indicates the peer closed the  

  198.                // connection.  

  199.                if (RecvBytes == 0)  

  200.                {  

  201.                   FreeSocketInformation(i);  

  202.                   continue;  

  203.                }  

  204.             }  

  205.          }  

  206.   

  207.   

  208.          // If the WriteSet is marked on this socket then this means the internal  

  209.          // data buffers are available for more data.  

  210.   

  211.          if (FD_ISSET(SocketInfo->Socket, &WriteSet))  

  212.          {  

  213.             Total--;  

  214.   

  215.             SocketInfo->DataBuf.buf = SocketInfo->Buffer + SocketInfo->BytesSEND;  

  216.             SocketInfo->DataBuf.len = SocketInfo->BytesRECV - SocketInfo->BytesSEND;  

  217.   

  218.             if (WSASend(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &SendBytes, 0,  

  219.                NULL, NULL) == SOCKET_ERROR)  

  220.             {  

  221.                if (WSAGetLastError() != WSAEWOULDBLOCK)  

  222.                {  

  223.                   printf("WSASend() failed with error %d/n", WSAGetLastError());  

  224.   

  225.                   FreeSocketInformation(i);  

  226.                }  

  227.   

  228.                continue;  

  229.             }  

  230.             else  

  231.             {  

  232.                SocketInfo->BytesSEND += SendBytes;  

  233.   

  234.                if (SocketInfo->BytesSEND == SocketInfo->BytesRECV)  

  235.                {  

  236.                   SocketInfo->BytesSEND = 0;  

  237.                   SocketInfo->BytesRECV = 0;  

  238.                }  

  239.             }  

  240.          }  

  241.       }  

  242.    }  

  243. }  

  244.   

  245. BOOL CreateSocketInformation(SOCKET s)  

  246. {  

  247.    LPSOCKET_INFORMATION SI;  

  248.         

  249.    printf("Accepted socket number %d/n", s);  

  250.   

  251.    if ((SI = (LPSOCKET_INFORMATION) GlobalAlloc(GPTR,  

  252.       sizeof(SOCKET_INFORMATION))) == NULL)  

  253.    {  

  254.       printf("GlobalAlloc() failed with error %d/n", GetLastError());  

  255.       return FALSE;  

  256.    }  

  257.   

  258.    // Prepare SocketInfo structure for use.  

  259.   

  260.    SI->Socket = s;  

  261.    SI->BytesSEND = 0;  

  262.    SI->BytesRECV = 0;  

  263.   

  264.    SocketArray[TotalSockets] = SI;  

  265.   

  266.    TotalSockets++;  

  267.   

  268.    return(TRUE);  

  269. }  

  270.   

  271. void FreeSocketInformation(DWORD Index)  

  272. {  

  273.    LPSOCKET_INFORMATION SI = SocketArray[Index];  

  274.    DWORD i;  

  275.   

  276.    closesocket(SI->Socket);  

  277.   

  278.    printf("Closing socket number %d/n", SI->Socket);  

  279.   

  280.    GlobalFree(SI);  

  281.   

  282.    // Squash the socket array  

  283.   

  284.    for (i = Index; i < TotalSockets; i++)  

  285.    {  

  286.       SocketArray[i] = SocketArray[i + 1];  

  287.    }  

  288.   

  289.    TotalSockets--;  

  290. }  

 

完成端口模型

 

  1. // Module Name: iocmplt.cpp   

  2. //   

  3. // Description:   

  4. //   

  5. //    This sample illustrates how to develop a simple echo server Winsock   

  6. //    application using the completeion port I/O model. This    

  7. //    sample is implemented as a console-style application and simply prints   

  8. //    messages when connections are established and removed from the server.   

  9. //    The application listens for TCP connections on port 5150 and accepts them   

  10. //    as they arrive. When this application receives data from a client, it   

  11. //    simply echos (this is why we call it an echo server) the data back in   

  12. //    it's original form until the client closes the connection.   

  13. //   

  14. // Compile:   

  15. //   

  16. //    cl -o iocmplt iocmplt.cpp ws2_32.lib   

  17. //   

  18. // Command Line Options:   

  19. //   

  20. //    iocmplt.exe    

  21. //   

  22. //    Note: There are no command line options for this sample.   

  23.   

  24. #include <winsock2.h>   

  25. #include <windows.h>   

  26. #include <stdio.h>   

  27.   

  28. #define PORT 5150   

  29. #define DATA_BUFSIZE 8192   

  30.   

  31. typedef struct  

  32. {   

  33.    OVERLAPPED Overlapped;   

  34.    WSABUF DataBuf;   

  35.    CHAR Buffer[DATA_BUFSIZE];   

  36.    DWORD BytesSEND;   

  37.    DWORD BytesRECV;   

  38. } PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;   

  39.   

  40.   

  41. typedef struct    

  42. {   

  43.    SOCKET Socket;   

  44. } PER_HANDLE_DATA, * LPPER_HANDLE_DATA;   

  45.   

  46.   

  47. DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);   

  48.   

  49. void main(void)   

  50. {   

  51.    SOCKADDR_IN InternetAddr;   

  52.    SOCKET Listen;   

  53.    SOCKET Accept;   

  54.    HANDLE CompletionPort;   

  55.    SYSTEM_INFO SystemInfo;   

  56.    LPPER_HANDLE_DATA PerHandleData;   

  57.    LPPER_IO_OPERATION_DATA PerIoData;   

  58.    int i;   

  59.    DWORD RecvBytes;   

  60.    DWORD Flags;   

  61.    DWORD ThreadID;   

  62.    WSADATA wsaData;   

  63.    DWORD Ret;   

  64.   

  65.    if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)   

  66.    {   

  67.       printf("WSAStartup failed with error %d/n", Ret);   

  68.       return;   

  69.    }   

  70.   

  71.    // Setup an I/O completion port.   

  72.   

  73.    if ((CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)) == NULL)   

  74.    {   

  75.       printf( "CreateIoCompletionPort failed with error: %d/n", GetLastError());   

  76.       return;   

  77.    }   

  78.   

  79.    // Determine how many processors are on the system.   

  80.   

  81.    GetSystemInfo(&SystemInfo);   

  82.   

  83.    // Create worker threads based on the number of processors available on the   

  84.    // system. Create two worker threads for each processor.   

  85.   

  86.    for(i = 0; i < SystemInfo.dwNumberOfProcessors * 2; i++)   

  87.    {   

  88.       HANDLE ThreadHandle;   

  89.   

  90.       // Create a server worker thread and pass the completion port to the thread.   

  91.   

  92.       if ((ThreadHandle = CreateThread(NULL, 0, ServerWorkerThread, CompletionPort,   

  93.          0, &ThreadID)) == NULL)   

  94.       {   

  95.          printf("CreateThread() failed with error %d/n", GetLastError());   

  96.          return;   

  97.       }   

  98.   

  99.       // Close the thread handle   

  100.       CloseHandle(ThreadHandle);   

  101.    }   

  102.   

  103.    // Create a listening socket   

  104.   

  105.    if ((Listen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,   

  106.       WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)   

  107.    {   

  108.       printf("WSASocket() failed with error %d/n", WSAGetLastError());   

  109.       return;   

  110.    }    

  111.   

  112.    InternetAddr.sin_family = AF_INET;   

  113.    InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);   

  114.    InternetAddr.sin_port = htons(PORT);   

  115.   

  116.    if (bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)   

  117.    {   

  118.       printf("bind() failed with error %d/n", WSAGetLastError());   

  119.       return;   

  120.    }   

  121.   

  122.    // Prepare socket for listening   

  123.   

  124.    if (listen(Listen, 5) == SOCKET_ERROR)   

  125.    {   

  126.       printf("listen() failed with error %d/n", WSAGetLastError());   

  127.       return;   

  128.    }   

  129.   

  130.    // Accept connections and assign to the completion port.   

  131.   

  132.    while(TRUE)   

  133.    {   

  134.       if ((Accept = WSAAccept(Listen, NULL, NULL, NULL, 0)) == SOCKET_ERROR)   

  135.       {   

  136.          printf("WSAAccept() failed with error %d/n", WSAGetLastError());   

  137.          return;   

  138.       }   

  139.   

  140.       // Create a socket information structure to associate with the socket   

  141.       if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR,    

  142.          sizeof(PER_HANDLE_DATA))) == NULL)   

  143.       {   

  144.          printf("GlobalAlloc() failed with error %d/n", GetLastError());   

  145.          return;   

  146.       }   

  147.   

  148.       // Associate the accepted socket with the original completion port.   

  149.   

  150.       printf("Socket number %d connected/n", Accept);   

  151.       PerHandleData->Socket = Accept;   

  152.   

  153.       if (CreateIoCompletionPort((HANDLE) Accept, CompletionPort, (DWORD) PerHandleData,   

  154.          0) == NULL)   

  155.       {   

  156.          printf("CreateIoCompletionPort failed with error %d/n", GetLastError());   

  157.          return;   

  158.       }   

  159.   

  160.       // Create per I/O socket information structure to associate with the    

  161.       // WSARecv call below.   

  162.   

  163.       if ((PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR,          sizeof(PER_IO_OPERATION_DATA))) == NULL)   

  164.       {   

  165.          printf("GlobalAlloc() failed with error %d/n", GetLastError());   

  166.          return;   

  167.       }   

  168.   

  169.       ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));   

  170.       PerIoData->BytesSEND = 0;   

  171.       PerIoData->BytesRECV = 0;   

  172.       PerIoData->DataBuf.len = DATA_BUFSIZE;   

  173.       PerIoData->DataBuf.buf = PerIoData->Buffer;   

  174.   

  175.       Flags = 0;   

  176.       if (WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,   

  177.          &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)   

  178.       {   

  179.          if (WSAGetLastError() != ERROR_IO_PENDING)   

  180.          {   

  181.             printf("WSARecv() failed with error %d/n", WSAGetLastError());   

  182.             return;   

  183.          }   

  184.       }   

  185.    }   

  186. }   

  187.   

  188. DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)   

  189. {   

  190.    HANDLE CompletionPort = (HANDLE) CompletionPortID;   

  191.    DWORD BytesTransferred;   

  192.    LPOVERLAPPED Overlapped;   

  193.    LPPER_HANDLE_DATA PerHandleData;   

  194.    LPPER_IO_OPERATION_DATA PerIoData;   

  195.    DWORD SendBytes, RecvBytes;   

  196.    DWORD Flags;   

  197.       

  198.    while(TRUE)   

  199.    {   

  200.            

  201.       if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,   

  202.          (LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == 0)   

  203.       {   

  204.          printf("GetQueuedCompletionStatus failed with error %d/n", GetLastError());   

  205.          return 0;   

  206.       }   

  207.   

  208.   

  209.       // First check to see if an error has occured on the socket and if so   

  210.       // then close the socket and cleanup the SOCKET_INFORMATION structure   

  211.       // associated with the socket.   

  212.   

  213.       if (BytesTransferred == 0)   

  214.       {   

  215.          printf("Closing socket %d/n", PerHandleData->Socket);   

  216.   

  217.          if (closesocket(PerHandleData->Socket) == SOCKET_ERROR)   

  218.          {   

  219.             printf("closesocket() failed with error %d/n", WSAGetLastError());   

  220.             return 0;   

  221.          }   

  222.   

  223.          GlobalFree(PerHandleData);   

  224.          GlobalFree(PerIoData);   

  225.          continue;   

  226.       }   

  227.   

  228.       // Check to see if the BytesRECV field equals zero. If this is so, then   

  229.       // this means a WSARecv call just completed so update the BytesRECV field   

  230.       // with the BytesTransferred value from the completed WSARecv() call.   

  231.   

  232.       if (PerIoData->BytesRECV == 0)   

  233.       {   

  234.          PerIoData->BytesRECV = BytesTransferred;   

  235.          PerIoData->BytesSEND = 0;   

  236.       }   

  237.       else  

  238.       {   

  239.          PerIoData->BytesSEND += BytesTransferred;   

  240.       }   

  241.   

  242.       if (PerIoData->BytesRECV > PerIoData->BytesSEND)   

  243.       {   

  244.   

  245.          // Post another WSASend() request.   

  246.          // Since WSASend() is not gauranteed to send all of the bytes requested,   

  247.          // continue posting WSASend() calls until all received bytes are sent.   

  248.   

  249.          ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));   

  250.   

  251.          PerIoData->DataBuf.buf = PerIoData->Buffer + PerIoData->BytesSEND;   

  252.          PerIoData->DataBuf.len = PerIoData->BytesRECV - PerIoData->BytesSEND;   

  253.   

  254.          if (WSASend(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &SendBytes, 0,   

  255.             &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)   

  256.          {   

  257.             if (WSAGetLastError() != ERROR_IO_PENDING)   

  258.             {   

  259.                printf("WSASend() failed with error %d/n", WSAGetLastError());   

  260.                return 0;   

  261.             }   

  262.          }   

  263.       }   

  264.       else  

  265.       {   

  266.          PerIoData->BytesRECV = 0;   

  267.   

  268.          // Now that there are no more bytes to send post another WSARecv() request.   

  269.   

  270.          Flags = 0;   

  271.          ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));   

  272.   

  273.          PerIoData->DataBuf.len = DATA_BUFSIZE;   

  274.          PerIoData->DataBuf.buf = PerIoData->Buffer;   

  275.   

  276.          if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,   

  277.             &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)   

  278.          {   

  279.             if (WSAGetLastError() != ERROR_IO_PENDING)   

  280.             {   

  281.                printf("WSARecv() failed with error %d/n", WSAGetLastError());   

  282.                return 0;   

  283.             }   

  284.          }   

  285.       }   

  286.    }   

  287. }  

[cpp] 

  1. // Module Name: iocmplt.cpp  

  2. //  

  3. // Description:  

  4. //  

  5. //    This sample illustrates how to develop a simple echo server Winsock  

  6. //    application using the completeion port I/O model. This   

  7. //    sample is implemented as a console-style application and simply prints  

  8. //    messages when connections are established and removed from the server.  

  9. //    The application listens for TCP connections on port 5150 and accepts them  

  10. //    as they arrive. When this application receives data from a client, it  

  11. //    simply echos (this is why we call it an echo server) the data back in  

  12. //    it's original form until the client closes the connection.  

  13. //  

  14. // Compile:  

  15. //  

  16. //    cl -o iocmplt iocmplt.cpp ws2_32.lib  

  17. //  

  18. // Command Line Options:  

  19. //  

  20. //    iocmplt.exe   

  21. //  

  22. //    Note: There are no command line options for this sample.  

  23.   

  24. #include <winsock2.h>  

  25. #include <windows.h>  

  26. #include <stdio.h>  

  27.   

  28. #define PORT 5150  

  29. #define DATA_BUFSIZE 8192  

  30.   

  31. typedef struct  

  32. {  

  33.    OVERLAPPED Overlapped;  

  34.    WSABUF DataBuf;  

  35.    CHAR Buffer[DATA_BUFSIZE];  

  36.    DWORD BytesSEND;  

  37.    DWORD BytesRECV;  

  38. } PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;  

  39.   

  40.   

  41. typedef struct   

  42. {  

  43.    SOCKET Socket;  

  44. } PER_HANDLE_DATA, * LPPER_HANDLE_DATA;  

  45.   

  46.   

  47. DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);  

  48.   

  49. void main(void)  

  50. {  

  51.    SOCKADDR_IN InternetAddr;  

  52.    SOCKET Listen;  

  53.    SOCKET Accept;  

  54.    HANDLE CompletionPort;  

  55.    SYSTEM_INFO SystemInfo;  

  56.    LPPER_HANDLE_DATA PerHandleData;  

  57.    LPPER_IO_OPERATION_DATA PerIoData;  

  58.    int i;  

  59.    DWORD RecvBytes;  

  60.    DWORD Flags;  

  61.    DWORD ThreadID;  

  62.    WSADATA wsaData;  

  63.    DWORD Ret;  

  64.   

  65.    if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)  

  66.    {  

  67.       printf("WSAStartup failed with error %d/n", Ret);  

  68.       return;  

  69.    }  

  70.   

  71.    // Setup an I/O completion port.  

  72.   

  73.    if ((CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)) == NULL)  

  74.    {  

  75.       printf( "CreateIoCompletionPort failed with error: %d/n", GetLastError());  

  76.       return;  

  77.    }  

  78.   

  79.    // Determine how many processors are on the system.  

  80.   

  81.    GetSystemInfo(&SystemInfo);  

  82.   

  83.    // Create worker threads based on the number of processors available on the  

  84.    // system. Create two worker threads for each processor.  

  85.   

  86.    for(i = 0; i < SystemInfo.dwNumberOfProcessors * 2; i++)  

  87.    {  

  88.       HANDLE ThreadHandle;  

  89.   

  90.       // Create a server worker thread and pass the completion port to the thread.  

  91.   

  92.       if ((ThreadHandle = CreateThread(NULL, 0, ServerWorkerThread, CompletionPort,  

  93.          0, &ThreadID)) == NULL)  

  94.       {  

  95.          printf("CreateThread() failed with error %d/n", GetLastError());  

  96.          return;  

  97.       }  

  98.   

  99.       // Close the thread handle  

  100.       CloseHandle(ThreadHandle);  

  101.    }  

  102.   

  103.    // Create a listening socket  

  104.   

  105.    if ((Listen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,  

  106.       WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)  

  107.    {  

  108.       printf("WSASocket() failed with error %d/n", WSAGetLastError());  

  109.       return;  

  110.    }   

  111.   

  112.    InternetAddr.sin_family = AF_INET;  

  113.    InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);  

  114.    InternetAddr.sin_port = htons(PORT);  

  115.   

  116.    if (bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)  

  117.    {  

  118.       printf("bind() failed with error %d/n", WSAGetLastError());  

  119.       return;  

  120.    }  

  121.   

  122.    // Prepare socket for listening  

  123.   

  124.    if (listen(Listen, 5) == SOCKET_ERROR)  

  125.    {  

  126.       printf("listen() failed with error %d/n", WSAGetLastError());  

  127.       return;  

  128.    }  

  129.   

  130.    // Accept connections and assign to the completion port.  

  131.   

  132.    while(TRUE)  

  133.    {  

  134.       if ((Accept = WSAAccept(Listen, NULL, NULL, NULL, 0)) == SOCKET_ERROR)  

  135.       {  

  136.          printf("WSAAccept() failed with error %d/n", WSAGetLastError());  

  137.          return;  

  138.       }  

  139.   

  140.       // Create a socket information structure to associate with the socket  

  141.       if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR,   

  142.          sizeof(PER_HANDLE_DATA))) == NULL)  

  143.       {  

  144.          printf("GlobalAlloc() failed with error %d/n", GetLastError());  

  145.          return;  

  146.       }  

  147.   

  148.       // Associate the accepted socket with the original completion port.  

  149.   

  150.       printf("Socket number %d connected/n", Accept);  

  151.       PerHandleData->Socket = Accept;  

  152.   

  153.       if (CreateIoCompletionPort((HANDLE) Accept, CompletionPort, (DWORD) PerHandleData,  

  154.          0) == NULL)  

  155.       {  

  156.          printf("CreateIoCompletionPort failed with error %d/n", GetLastError());  

  157.          return;  

  158.       }  

  159.   

  160.       // Create per I/O socket information structure to associate with the   

  161.       // WSARecv call below.  

  162.   

  163.       if ((PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR,          sizeof(PER_IO_OPERATION_DATA))) == NULL)  

  164.       {  

  165.          printf("GlobalAlloc() failed with error %d/n", GetLastError());  

  166.          return;  

  167.       }  

  168.   

  169.       ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));  

  170.       PerIoData->BytesSEND = 0;  

  171.       PerIoData->BytesRECV = 0;  

  172.       PerIoData->DataBuf.len = DATA_BUFSIZE;  

  173.       PerIoData->DataBuf.buf = PerIoData->Buffer;  

  174.   

  175.       Flags = 0;  

  176.       if (WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,  

  177.          &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)  

  178.       {  

  179.          if (WSAGetLastError() != ERROR_IO_PENDING)  

  180.          {  

  181.             printf("WSARecv() failed with error %d/n", WSAGetLastError());  

  182.             return;  

  183.          }  

  184.       }  

  185.    }  

  186. }  

  187.   

  188. DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)  

  189. {  

  190.    HANDLE CompletionPort = (HANDLE) CompletionPortID;  

  191.    DWORD BytesTransferred;  

  192.    LPOVERLAPPED Overlapped;  

  193.    LPPER_HANDLE_DATA PerHandleData;  

  194.    LPPER_IO_OPERATION_DATA PerIoData;  

  195.    DWORD SendBytes, RecvBytes;  

  196.    DWORD Flags;  

  197.      

  198.    while(TRUE)  

  199.    {  

  200.           

  201.       if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,  

  202.          (LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == 0)  

  203.       {  

  204.          printf("GetQueuedCompletionStatus failed with error %d/n", GetLastError());  

  205.          return 0;  

  206.       }  

  207.   

  208.   

  209.       // First check to see if an error has occured on the socket and if so  

  210.       // then close the socket and cleanup the SOCKET_INFORMATION structure  

  211.       // associated with the socket.  

  212.   

  213.       if (BytesTransferred == 0)  

  214.       {  

  215.          printf("Closing socket %d/n", PerHandleData->Socket);  

  216.   

  217.          if (closesocket(PerHandleData->Socket) == SOCKET_ERROR)  

  218.          {  

  219.             printf("closesocket() failed with error %d/n", WSAGetLastError());  

  220.             return 0;  

  221.          }  

  222.   

  223.          GlobalFree(PerHandleData);  

  224.          GlobalFree(PerIoData);  

  225.          continue;  

  226.       }  

  227.   

  228.       // Check to see if the BytesRECV field equals zero. If this is so, then  

  229.       // this means a WSARecv call just completed so update the BytesRECV field  

  230.       // with the BytesTransferred value from the completed WSARecv() call.  

  231.   

  232.       if (PerIoData->BytesRECV == 0)  

  233.       {  

  234.          PerIoData->BytesRECV = BytesTransferred;  

  235.          PerIoData->BytesSEND = 0;  

  236.       }  

  237.       else  

  238.       {  

  239.          PerIoData->BytesSEND += BytesTransferred;  

  240.       }  

  241.   

  242.       if (PerIoData->BytesRECV > PerIoData->BytesSEND)  

  243.       {  

  244.   

  245.          // Post another WSASend() request.  

  246.          // Since WSASend() is not gauranteed to send all of the bytes requested,  

  247.          // continue posting WSASend() calls until all received bytes are sent.  

  248.   

  249.          ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));  

  250.   

  251.          PerIoData->DataBuf.buf = PerIoData->Buffer + PerIoData->BytesSEND;  

  252.          PerIoData->DataBuf.len = PerIoData->BytesRECV - PerIoData->BytesSEND;  

  253.   

  254.          if (WSASend(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &SendBytes, 0,  

  255.             &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)  

  256.          {  

  257.             if (WSAGetLastError() != ERROR_IO_PENDING)  

  258.             {  

  259.                printf("WSASend() failed with error %d/n", WSAGetLastError());  

  260.                return 0;  

  261.             }  

  262.          }  

  263.       }  

  264.       else  

  265.       {  

  266.          PerIoData->BytesRECV = 0;  

  267.   

  268.          // Now that there are no more bytes to send post another WSARecv() request.  

  269.   

  270.          Flags = 0;  

  271.          ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));  

  272.   

  273.          PerIoData->DataBuf.len = DATA_BUFSIZE;  

  274.          PerIoData->DataBuf.buf = PerIoData->Buffer;  

  275.   

  276.          if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,  

  277.             &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)  

  278.          {  

  279.             if (WSAGetLastError() != ERROR_IO_PENDING)  

  280.             {  

  281.                printf("WSARecv() failed with error %d/n", WSAGetLastError());  

  282.                return 0;  

  283.             }  

  284.          }  

  285.       }  

  286.    }  

  287. }  

 

 

 

  1. void memcpyHtol(int &des, char* &str)   

  2. {   

  3.     int len = sizeof(des);   

  4.     memcpy(&des, str, len);   

  5.     des = htonl(des);   

  6.     str += len;   

  7. }  

[cpp] 

  1. void memcpyHtol(int &des, char* &str)  

  2. {  

  3.     int len = sizeof(des);  

  4.     memcpy(&des, str, len);  

  5.     des = htonl(des);  

  6.     str += len;  

  7. }

你可能感兴趣的:(windows网络编程)