文章一:http://baike.soso.com/v5865322.htm
http://wenku.baidu.com/view/17eb0c2f0066f5335a812136.html
文章二:
http://kevensnowgirl.blog.hexun.com/6811572_d.html
http://xingzhesun.blogbus.com/c1584116/
客户端代码
// Client.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <WinSock2.h>
#include <stdio.h>
//不加ws2_32.lib的话就需要动态的加载
#pragma comment(lib, "ws2_32.lib")
#define SERVER_ADDRESS "127.0.0.1"
#define PORT 5150
#define MSGSIZE 1024
#define CPORT 7001
int _tmain(int argc, _TCHAR* argv[])
{
//Initialize Window socket library
WSADATA wsaData;
WSAStartup(0x0202, &wsaData);
//Create Socket;
SOCKET sClient;
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
//Connect to Server
SOCKADDR_IN server;
memset(&server, 0, sizeof(SOCKADDR_IN));
server.sin_addr.S_un.S_addr = inet_addr(SERVER_ADDRESS);
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
int ret = connect(sClient, (sockaddr*)&server, sizeof(SOCKADDR_IN));
if(ret == SOCKET_ERROR)
{
printf("connet error = %d \n", WSAGetLastError());
goto exit;
}
//send message
char szMessage[MSGSIZE];
while(true)
{
printf("Send:");
gets(szMessage);
if(0 == strcmp("exit" , szMessage))
{
goto exit;
}
//send message
send(sClient, szMessage, sizeof(szMessage), 0);
memset(szMessage, 0, sizeof(szMessage));
//receive message
ret = recv(sClient, szMessage, MSGSIZE, 0);
szMessage[ret] = '\0';
printf("REceived [%d bytes]: '%s'\n ", ret, szMessage);
}
exit:
closesocket(sClient);
WSACleanup();
return 0;
}
服务器端代码
// server_CompletionPort.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")
#define PORT 5150
#define MSGSIZE 1024
typedef enum
{
RECV_POSTED
}OPERATION_TYPE;
typedef struct
{
WSAOVERLAPPED overlap;
WSABUF Buffer;
char szMessage[MSGSIZE];
DWORD NumberOfBytesRecvd;
DWORD Flags;
OPERATION_TYPE OperationType;
}PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;
DWORD WINAPI WorkerThread(LPVOID CompletionPortID)
{
HANDLE CompletionPort = (HANDLE)CompletionPortID;
DWORD dwBytesTransferred;
SOCKET sClient;
LPPER_IO_OPERATION_DATA lpPerIOData = NULL;
while(true)
{
//this method to check whether the completionPort queue exist request,
//if exist, it will run the following code, if not exist, it will waiting
GetQueuedCompletionStatus(
CompletionPort,
&dwBytesTransferred,
(unsigned long*)&sClient,
(LPOVERLAPPED*)&lpPerIOData,
INFINITE
);
if(dwBytesTransferred == 0xFFFFFFFF)
{
return 0;
}
if(lpPerIOData->OperationType == RECV_POSTED)
{
if(dwBytesTransferred == 0)
{
//connection was closed by client
closesocket(sClient);
HeapFree(GetProcessHeap(), 0, lpPerIOData);
}
else
{
lpPerIOData->szMessage[dwBytesTransferred] = '\0';
send(sClient, lpPerIOData->szMessage, dwBytesTransferred, 0);
//launch another asynchronous operation for sClient
///*********************************************************
memset(lpPerIOData, 0 , sizeof(PER_IO_OPERATION_DATA));
lpPerIOData->Buffer.len = MSGSIZE;
lpPerIOData->Buffer.buf = lpPerIOData->szMessage;
lpPerIOData->OperationType = RECV_POSTED;
WSARecv(
sClient,
&lpPerIOData->Buffer,
1,
&lpPerIOData->NumberOfBytesRecvd,
&lpPerIOData->Flags,
&lpPerIOData->overlap,
NULL
);
///*********************************************************
}
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
//1. Initialize Windows Socket library
WSADATA wsaData;
WSAStartup(0x0202, &wsaData);
//*2. Create Completion port, save its handle, and this handle will useful
HANDLE CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
//*3. Create Worker Thread
//3.1 the thread number is same as the Processor number
//3.2 this thread is use to commnute with the client
SYSTEM_INFO systeminfo;
GetSystemInfo(&systeminfo);
DWORD dwThreadId;
for(int i=0 ; i < systeminfo.dwNumberOfProcessors; i++)
{
CreateThread(NULL, 0, WorkerThread, CompletionPort, 0, &dwThreadId);
}
SOCKET sListen, sClient= NULL;
//4. Create listening socket
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
//5. Bind
SOCKADDR_IN local, client;
local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
local.sin_family = AF_INET;
local.sin_port = htons(PORT);
bind(sListen, (sockaddr*)&local, sizeof(SOCKADDR_IN));
printf("Binded\n");
//6. Listen
listen(sListen, 3);
printf("Listened\n");
LPPER_IO_OPERATION_DATA lpPerIOData = NULL;
int nLen = sizeof(sockaddr);
while(true)
{
printf("Accepting...\n");
//7. accept a connection
sClient = accept(sListen, (sockaddr*)&client, &nLen);
printf("Accepted client:%s : %d, &%d \n",
inet_ntoa(client.sin_addr), ntohs(client.sin_port),WSAGetLastError());
//*8. Associate the newly arrived client socket with completion port
//8.1 Whenever the client connect to server, use this method again,
// but this time its function is to bind with the new Socket with the completionPort
//8.2 After this method create, the preparetion is completed. following with send or recv it.
CreateIoCompletionPort((HANDLE)sClient, CompletionPort, (DWORD)sClient, 0);
//Launch an asynchronous operation for new arrived connetion
///*********************************************************
lpPerIOData = (LPPER_IO_OPERATION_DATA)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(PER_IO_OPERATION_DATA)
);
lpPerIOData->Buffer.len = MSGSIZE;
lpPerIOData->Buffer.buf = lpPerIOData->szMessage;
lpPerIOData->OperationType = RECV_POSTED;
WSARecv(
sClient,
&lpPerIOData->Buffer,
1,
&lpPerIOData->NumberOfBytesRecvd,
&lpPerIOData->Flags,
&lpPerIOData->overlap,
NULL
);
///*********************************************************
}
PostQueuedCompletionStatus(CompletionPort, 0xFFFFFFFF, 0, NULL);
CloseHandle(CompletionPort);
closesocket(sListen);
WSACleanup();
return 0;
}