基于对话框,引入Windows Socket!如何编写完成端口?
请给出思路!
谢谢!

解决方案 »

  1.   

    见windows 网络编程 iocp
      

  2.   

    一个简单的完成端口的例子:
    // Module Name: iocmplt.cpp
    //
    // Description:
    //
    //    This sample illustrates how to develop a simple echo server Winsock
    //    application using the completeion port I/O model. This 
    //    sample is implemented as a console-style application and simply prints
    //    messages when connections are established and removed from the server.
    //    The application listens for TCP connections on port 5150 and accepts them
    //    as they arrive. When this application receives data from a client, it
    //    simply echos (this is why we call it an echo server) the data back in
    //    it's original form until the client closes the connection.
    //
    // Compile:
    //
    //    cl -o iocmplt iocmplt.cpp ws2_32.lib
    //
    // Command Line Options:
    //
    //    iocmplt.exe 
    //
    //    Note: There are no command line options for this sample.#include <winsock2.h>
    #include <windows.h>
    #include <stdio.h>#define PORT 5150
    #define DATA_BUFSIZE 8192typedef struct
    {
       OVERLAPPED Overlapped;
       WSABUF DataBuf;
       CHAR Buffer[DATA_BUFSIZE];
       DWORD BytesSEND;
       DWORD BytesRECV;
    } PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;
    typedef struct 
    {
       SOCKET Socket;
    } PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
    DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);void main(void)
    {
       SOCKADDR_IN InternetAddr;
       SOCKET Listen;
       SOCKET Accept;
       HANDLE CompletionPort;
       SYSTEM_INFO SystemInfo;
       LPPER_HANDLE_DATA PerHandleData;
       LPPER_IO_OPERATION_DATA PerIoData;
       int i;
       DWORD RecvBytes;
       DWORD Flags;
       DWORD ThreadID;
       WSADATA wsaData;
       DWORD Ret;   if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
       {
          printf("WSAStartup failed with error %d\n", Ret);
          return;
       }   // Setup an I/O completion port.   if ((CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)) == NULL)
       {
          printf( "CreateIoCompletionPort failed with error: %d\n", GetLastError());
          return;
       }   // Determine how many processors are on the system.   GetSystemInfo(&SystemInfo);   // Create worker threads based on the number of processors available on the
       // system. Create two worker threads for each processor.   for(i = 0; i < SystemInfo.dwNumberOfProcessors * 2; i++)
       {
          HANDLE ThreadHandle;      // Create a server worker thread and pass the completion port to the thread.      if ((ThreadHandle = CreateThread(NULL, 0, ServerWorkerThread, CompletionPort,
             0, &ThreadID)) == NULL)
          {
             printf("CreateThread() failed with error %d\n", GetLastError());
             return;
          }      // Close the thread handle
          CloseHandle(ThreadHandle);
       }
      

  3.   

    // Create a listening socket   if ((Listen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,
          WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
       {
          printf("WSASocket() failed with error %d\n", WSAGetLastError());
          return;
       }    InternetAddr.sin_family = AF_INET;
       InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
       InternetAddr.sin_port = htons(PORT);   if (bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
       {
          printf("bind() failed with error %d\n", WSAGetLastError());
          return;
       }   // Prepare socket for listening   if (listen(Listen, 5) == SOCKET_ERROR)
       {
          printf("listen() failed with error %d\n", WSAGetLastError());
          return;
       }
    // Accept connections and assign to the completion port.   while(TRUE)
       {
          if ((Accept = WSAAccept(Listen, NULL, NULL, NULL, 0)) == SOCKET_ERROR)
          {
             printf("WSAAccept() failed with error %d\n", WSAGetLastError());
             return;
          }      // Create a socket information structure to associate with the socket
          if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR, 
             sizeof(PER_HANDLE_DATA))) == NULL)
          {
             printf("GlobalAlloc() failed with error %d\n", GetLastError());
             return;
          }      // Associate the accepted socket with the original completion port.      printf("Socket number %d connected\n", Accept);
          PerHandleData->Socket = Accept;      if (CreateIoCompletionPort((HANDLE)Accept, CompletionPort, (DWORD) PerHandleData,  0) == NULL)
          {
             printf("CreateIoCompletionPort failed with error %d\n", GetLastError());
             return;
          }      // Create per I/O socket information structure to associate with the 
          // WSARecv call below.      if ((PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR,          sizeof(PER_IO_OPERATION_DATA))) == NULL)
          {
             printf("GlobalAlloc() failed with error %d\n", GetLastError());
             return;
          }      ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
          PerIoData->BytesSEND = 0;
          PerIoData->BytesRECV = 0;
          PerIoData->DataBuf.len = DATA_BUFSIZE;
          PerIoData->DataBuf.buf = PerIoData->Buffer;      Flags = 0;
          if (WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,
             &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
          {
             if (WSAGetLastError() != ERROR_IO_PENDING)
             {
                printf("WSARecv() failed with error %d\n", WSAGetLastError());
                return;
             }
          }
       }
    }DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
    {
       HANDLE CompletionPort = (HANDLE) CompletionPortID;
       DWORD BytesTransferred;
       LPOVERLAPPED Overlapped;
       LPPER_HANDLE_DATA PerHandleData;
       LPPER_IO_OPERATION_DATA PerIoData;
       DWORD SendBytes, RecvBytes;
       DWORD Flags;
       
       while(TRUE)
       {      if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
             (LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == 0)
          {
             printf("GetQueuedCompletionStatus failed with error %d\n", GetLastError());
             return 0;
          }
          // First check to see if an error has occured on the socket and if so
          // then close the socket and cleanup the SOCKET_INFORMATION structure
          // associated with the socket.      if (BytesTransferred == 0)
          {
             printf("Closing socket %d\n", PerHandleData->Socket);         if (closesocket(PerHandleData->Socket) == SOCKET_ERROR)
             {
                printf("closesocket() failed with error %d\n", WSAGetLastError());
                return 0;
             }         GlobalFree(PerHandleData);
             GlobalFree(PerIoData);
             continue;
          }      // Check to see if the BytesRECV field equals zero. If this is so, then
          // this means a WSARecv call just completed so update the BytesRECV field
          // with the BytesTransferred value from the completed WSARecv() call.      if (PerIoData->BytesRECV == 0)
          {
             PerIoData->BytesRECV = BytesTransferred;
             PerIoData->BytesSEND = 0;
          }
          else
          {
             PerIoData->BytesSEND += BytesTransferred;
          }      if (PerIoData->BytesRECV > PerIoData->BytesSEND)
          {         // Post another WSASend() request.
             // Since WSASend() is not gauranteed to send all of the bytes requested,
             // continue posting WSASend() calls until all received bytes are sent.         ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));         PerIoData->DataBuf.buf = PerIoData->Buffer + PerIoData->BytesSEND;
             PerIoData->DataBuf.len = PerIoData->BytesRECV - PerIoData->BytesSEND;         if (WSASend(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &SendBytes, 0,
                &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
             {
                if (WSAGetLastError() != ERROR_IO_PENDING)
                {
                   printf("WSASend() failed with error %d\n", WSAGetLastError());
                   return 0;
                }
             }
          }
          else
          {
             PerIoData->BytesRECV = 0;         // Now that there are no more bytes to send post another WSARecv() request.         Flags = 0;
             ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));         PerIoData->DataBuf.len = DATA_BUFSIZE;
             PerIoData->DataBuf.buf = PerIoData->Buffer;         if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
             {
                if (WSAGetLastError() != ERROR_IO_PENDING)
                {
                   printf("WSARecv() failed with error %d\n", WSAGetLastError());
                   return 0;
                }
             }
          }
       }
    }
      

  4.   

    根本不需要这么的麻烦:
    1 使用AfxSocketInit函数来完成相应的套接字库的版本调用和协商,可以在程序创建的时候调用
    2 创建一个服务器端的端口初始化工作。对于像聊天的程序可以使用基于UDP的编程。在这个函数中绑定端口。
    3 创建一个线程,用于实现发送和接受套接字。由于TCP和UDP的网络是基于阻塞的,因此,必须在线程中实现。
    4 创建客户端的程序,对于简单的可以通过响应一个按钮的消息来调用