http://blog.csdn.net/jaff20071234/article/details/6538357
连接:
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
个人总结:
学习完成端口时,采用完成端口编写的服务器示例:
- // CompletionPortServer.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include <WinSock2.h>
- #include <windows.h>
- #include <process.h>
- #pragma comment(lib, "ws2_32")
- #define DATA_BUFSIZE 10
- #define RECV_POSTED 0
- #define SEND_POSTED 1
- typedef struct _PER_HANDLE_DATA
- {
- SOCKET Socket;
- SOCKADDR_STORAGE ClientAddr;
- // Other information useful to be associated with the handle
- } PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
- typedef struct
- {
- OVERLAPPED Overlapped;
- WSABUF DataBuf;
- char Buffer[DATA_BUFSIZE];
- int BufferLen;
- int OperationType;
- } PER_IO_DATA, *LPPER_IO_DATA;
- int StartWinsock( )
- {
- WORD wVersionRequested;
- WSADATA wsaData;
- int err;
- wVersionRequested = MAKEWORD( 2, 2 );
- err = WSAStartup( wVersionRequested, &wsaData );
- if ( err != 0 ) {
- /* Tell the user that we could not find a usable */
- /* WinSock DLL. */
- printf("error = %d/n", WSAGetLastError());
- return 0;
- }
- /* Confirm that the WinSock DLL supports 2.2.*/
- /* Note that if the DLL supports versions greater */
- /* than 2.2 in addition to 2.2, it will still return */
- /* 2.2 in wVersion since that is the version we */
- /* requested. */
- if ( LOBYTE( wsaData.wVersion ) != 2 ||
- HIBYTE( wsaData.wVersion ) != 2 ) {
- /* Tell the user that we could not find a usable */
- /* WinSock DLL. */
- WSACleanup( );
- return 0;
- }
- printf("max socket is :%d/n", wsaData.iMaxSockets);
- return 1;
- }
- unsigned int WINAPI __stdcall ServerWorkerThread(LPVOID CompletionPortID)
- {
- // The requirements for the worker thread will be
- // discussed later.
- HANDLE CompletionPort = (HANDLE) CompletionPortID;
- DWORD BytesTransferred;
- LPPER_HANDLE_DATA PerHandleData;
- LPPER_IO_DATA PerIoData;
- DWORD SendBytes, RecvBytes;
- DWORD Flags;
- int iRet = 0;
- while(1)
- {
- // Wait for I/O to complete on any socket
- // associated with the completion port
- iRet = GetQueuedCompletionStatus(CompletionPort,
- &BytesTransferred,(LPDWORD)&PerHandleData,
- (LPOVERLAPPED *) &PerIoData, INFINITE);
- // First check to see if an error has occurred
- // on the socket; if so, close the
- // socket and clean up the per-handle data
- // and per-I/O operation data associated with
- // the socket
- if ( BytesTransferred == 0 &&
- (PerIoData->OperationType == RECV_POSTED || PerIoData->OperationType == SEND_POSTED) )
- {
- // A zero BytesTransferred indicates that the
- // socket has been closed by the peer, so
- // you should close the socket. Note:
- // Per-handle data was used to reference the
- // socket associated with the I/O operation.
- closesocket(PerHandleData->Socket);
- GlobalFree(PerHandleData);
- GlobalFree(PerIoData);
- continue;
- }
- if (iRet == 0)
- {
- closesocket(PerHandleData->Socket);
- GlobalFree(PerHandleData);
- GlobalFree(PerIoData);
- continue;
- }
- if (BytesTransferred == -10)
- {
- // A zero BytesTransferred indicates that the
- // socket has been closed by the peer, so
- // you should close the socket. Note:
- // Per-handle data was used to reference the
- // socket associated with the I/O operation.
- closesocket(PerHandleData->Socket);
- GlobalFree(PerHandleData);
- GlobalFree(PerIoData);
- continue;
- }
- // Service the completed I/O request. You can
- // determine which I/O request has just
- // completed by looking at the OperationType
- // field contained in the per-I/O operation data.
- if (PerIoData->OperationType == RECV_POSTED)
- {
- // Do something with the received data
- // in PerIoData->Buffer
- printf("%s/n",PerIoData->Buffer);
- //Response:
- // Set up the per-I/O operation data for the next
- // overlapped call
- ZeroMemory(&(PerIoData->Overlapped),
- sizeof(OVERLAPPED));
- PerIoData->DataBuf.len = DATA_BUFSIZE;
- PerIoData->DataBuf.buf = PerIoData->Buffer;
- PerIoData->OperationType = SEND_POSTED;
- memset(PerIoData->Buffer, 0, DATA_BUFSIZE);
- strcpy_s(PerIoData->Buffer, DATA_BUFSIZE, "OK");
- //SendBytes = DATA_BUFSIZE;
- Flags = 0;
- iRet = WSASend(PerHandleData->Socket,
- &(PerIoData->DataBuf), 1, &SendBytes,
- Flags, &(PerIoData->Overlapped), NULL);
- if (iRet == SOCKET_ERROR)
- {
- if (WSAGetLastError() != WSA_IO_PENDING)
- {
- PostQueuedCompletionStatus(CompletionPort, -20, reinterpret_cast<DWORD> ((LPPER_HANDLE_DATA)&PerHandleData),
- (LPOVERLAPPED ) &PerIoData);
- }
- }
- printf("%d bytes data is sent /n", SendBytes);
- }
- else if (PerIoData->OperationType == SEND_POSTED)
- {
- // Post another WSASend or WSARecv operation.
- // As an example, we will post another WSARecv()
- // I/O operation.
- Flags = 0;
- // Set up the per-I/O operation data for the next
- // overlapped call
- ZeroMemory(&(PerIoData->Overlapped),
- sizeof(OVERLAPPED));
- PerIoData->DataBuf.len = DATA_BUFSIZE;
- PerIoData->DataBuf.buf = PerIoData->Buffer;
- PerIoData->OperationType = RECV_POSTED;
- iRet = WSARecv(PerHandleData->Socket,
- &(PerIoData->DataBuf), 1, &RecvBytes,
- &Flags, &(PerIoData->Overlapped), NULL);
- if (iRet == SOCKET_ERROR)
- {
- if (WSAGetLastError() != WSA_IO_PENDING)
- {
- PostQueuedCompletionStatus(CompletionPort, -10, reinterpret_cast<DWORD>((LPPER_HANDLE_DATA)&PerHandleData),
- (LPOVERLAPPED ) &PerIoData);
- }
- }
- }
- }
- }
- int _tmain()
- {
- SYSTEM_INFO stSysInfo;
- memset(&stSysInfo, 0, sizeof(stSysInfo));
- SOCKADDR_IN InternetAddr;
- SOCKET Listen;
- DWORD RecvBytes;
- DWORD Flags = 0;
- // Load Winsock
- int iResult = StartWinsock();
- if ( iResult == 0 )
- {
- printf("winsock start up failed./n, error = %d/n", WSAGetLastError());
- }
- // Create an I/O completion port
- // only processor's number thread is running by default.
- HANDLE hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
- // Determine how many processors are on the system
- GetSystemInfo(&stSysInfo);
- unsigned int i ;
- for(i = 0; i < stSysInfo.dwNumberOfProcessors; i++)
- {
- HANDLE ThreadHandle;
- // Create a server worker thread, and pass the
- // completion port to the thread. NOTE: the
- // ServerWorkerThread procedure is not defined
- // in this listing.
- ThreadHandle =(HANDLE) _beginthreadex(NULL, 0, ServerWorkerThread, hCompletionPort, 0, NULL);
- // Close the thread handle
- CloseHandle(ThreadHandle);
- }
- // Create a listening socket
- Listen = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
- WSA_FLAG_OVERLAPPED);
- int on = 1;
- setsockopt(Listen, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
- InternetAddr.sin_family = AF_INET;
- InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
- InternetAddr.sin_port = htons(5150);
- bind(Listen, (PSOCKADDR) &InternetAddr,
- sizeof(InternetAddr));
- // Prepare socket for listening
- listen(Listen, 5);
- while(1)
- {
- PER_HANDLE_DATA *PerHandleData=NULL;
- PER_IO_DATA *PerIoData = NULL;
- SOCKADDR_IN saRemote;
- SOCKET Accept;
- int RemoteLen;
- // Step 5:
- // Accept connections and assign to the completion
- // port
- RemoteLen = sizeof(saRemote);
- Accept = WSAAccept(Listen, (SOCKADDR *)&saRemote,
- &RemoteLen, NULL, NULL);
- // Step 6:
- // Create per-handle data information structure to
- // associate with the socket
- PerHandleData = (LPPER_HANDLE_DATA)
- GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA));
- PerIoData = (LPPER_IO_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_DATA));
- printf("Socket number %d connected/n", Accept);
- PerHandleData->Socket = Accept;
- memcpy(&PerHandleData->ClientAddr, &saRemote, RemoteLen);
- // Step 7:
- // Associate the accepted socket with the
- // completion port
- CreateIoCompletionPort((HANDLE) Accept,
- hCompletionPort, reinterpret_cast<DWORD>(PerHandleData), 0);
- // Set up the per-I/O operation data for the next
- // overlapped call
- ZeroMemory(&(PerIoData->Overlapped),
- sizeof(OVERLAPPED));
- PerIoData->DataBuf.len = DATA_BUFSIZE;
- PerIoData->DataBuf.buf = PerIoData->Buffer;
- PerIoData->OperationType = RECV_POSTED;
- 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 0;
- }
- }
- }
- return 0;
- }
客户端代码:
- // ClientTest.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include <winsock2.h>
- #include <process.h>
- #pragma comment(lib, "ws2_32")
- #define BUFSIZE 10
- int StartWinsock( )
- {
- WORD wVersionRequested;
- WSADATA wsaData;
- int err;
- wVersionRequested = MAKEWORD( 2, 2 );
- err = WSAStartup( wVersionRequested, &wsaData );
- if ( err != 0 ) {
- /* Tell the user that we could not find a usable */
- /* WinSock DLL. */
- printf("error = %d/n", WSAGetLastError());
- return 0;
- }
- /* Confirm that the WinSock DLL supports 2.2.*/
- /* Note that if the DLL supports versions greater */
- /* than 2.2 in addition to 2.2, it will still return */
- /* 2.2 in wVersion since that is the version we */
- /* requested. */
- if ( LOBYTE( wsaData.wVersion ) != 2 ||
- HIBYTE( wsaData.wVersion ) != 2 ) {
- /* Tell the user that we could not find a usable */
- /* WinSock DLL. */
- WSACleanup( );
- return 0;
- }
- printf("max socket is :%d/n", wsaData.iMaxSockets);
- return 1;
- }
- int count = 0;
- unsigned __stdcall WorkerThread(LPVOID pSock)
- {
- SOCKET clientSock = reinterpret_cast<SOCKET>(pSock);
- int iResult = 0;
- char buf[BUFSIZE];
- int i = 0;
- while ( i < 10 )
- {
- ZeroMemory(buf, BUFSIZE);
- memset(buf, 'E', BUFSIZE -1);
- //strcpy_s(buf, BUFSIZE, "1234567890");
- iResult = send(clientSock, buf, BUFSIZE, 0);
- if ( iResult == SOCKET_ERROR )
- {
- printf("%d个客户 send error = %d/n",count, WSAGetLastError());
- }
- ZeroMemory(buf, BUFSIZE);
- iResult = recv(clientSock, buf, BUFSIZE, 0);
- if ( iResult == SOCKET_ERROR )
- {
- printf("%d个客户 recv error = %d/n", count, WSAGetLastError());
- continue;
- }
- printf("received data is :%s/n", buf);
- i++;
- Sleep(2000);
- }
- iResult = shutdown(clientSock, SD_BOTH);
- if ( SOCKET_ERROR == iResult )
- {
- printf("%d个客户 shutdown error = %d/n", count, WSAGetLastError());
- }
- iResult = closesocket(clientSock);
- if ( SOCKET_ERROR == iResult )
- {
- printf("%d个客户 closesocket error = %d/n", count, WSAGetLastError());
- }
- return 0;
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- int iResult = StartWinsock();
- struct sockaddr_in serverAddr;
- memset(&serverAddr, 0 ,sizeof(serverAddr));
- serverAddr.sin_family = AF_INET;
- serverAddr.sin_port = htons(5150);
- serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
- while (1)
- {
- count++;
- printf("第%d个socket连接",count);
- SOCKET clientSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if ( clientSock ==INVALID_SOCKET )
- {
- printf("socket error = %d/n", WSAGetLastError());
- }
- iResult = connect(clientSock, (const sockaddr *)&serverAddr, sizeof(serverAddr));
- if ( iResult == SOCKET_ERROR )
- {
- printf("connect error = %d/n",WSAGetLastError());
- closesocket(clientSock);
- continue;
- }
- _beginthreadex(NULL, 0, WorkerThread, (LPVOID)clientSock, 0, NULL);
- Sleep(5000);
- }
- WSACleanup();
- return 0;
- }
可能存在一些资源未清理的情况,仅仅是做一个练习。