//////////////////////////////////////////////////////////////////////////
// 完成端口
//
//
//////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include
#include
#include
int InitSock();
DWORD WINAPI SerWorkThread(LPVOID CompletionPort);
// PerHandleData
typedef struct _PER_HANDLE_DATA
{
SOCKET socket;
SOCKADDR_IN ClientAddr;
}PER_HANDLE_DATA,*LPPER_HANDLE_DATA;
// Per IO operation Data
typedef struct _PER_IO_OPERATION_DATA
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
CHAR Buffer[8192];
DWORD BytesSEND;
DWORD BytesRECV;
}PER_IO_OPERATION_DATA,*LPPER_IO_OPERATION_DATA;
int main(int argc, char* argv[])
{
HANDLE hCompletionPort;
SYSTEM_INFO sysInfo;
int i = 0;
SOCKET Listen;
SOCKET Accept;
SOCKADDR_IN InetAddr;
DWORD Flags = 0;
DWORD RecvBytes = 0;
SOCKADDR_IN saRemote;
int saRemoteLen = sizeof(saRemote);
LPPER_HANDLE_DATA PerHandleData=NULL;
LPPER_IO_OPERATION_DATA PerIoOperationData=NULL;
if (!InitSock()) {
printf("InitSock Error!/n");
return 0;
}
//创建完成端口
hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
if (hCompletionPort == NULL) {
printf("Creatae CompletionPort Error!!/n");
return 0;
}
//创建工作者线程,线程数量和CPU数量保持一致
//工作者线程在IO请求到来的时候为完成端口提供服务。
GetSystemInfo(&sysInfo);
for ( i=0; i < (int)sysInfo.dwNumberOfProcessors ; i++ )
{
HANDLE hThread;
hThread = CreateThread(NULL,0,SerWorkThread,hCompletionPort,0,NULL);
if (hThread == NULL) {
printf("CreateThread Fail!");
}
CloseHandle(hThread);
}
//注意这里的SOCKET是TCP的
Listen = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
if (Listen == INVALID_SOCKET){
printf("Listen's socket error!/n");
return 0;
}
InetAddr.sin_family = AF_INET;
InetAddr.sin_port = htons(5010);
InetAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
if ( bind(Listen,(SOCKADDR*)&InetAddr,
sizeof(SOCKADDR))== SOCKET_ERROR) {
printf("Bind error/n");
return 0;
}
if ( listen(Listen,5)==SOCKET_ERROR ) { //注意这里的第二个参数
printf("Listen error/n");
return 0;
}
while (TRUE)
{
Accept = WSAAccept(Listen,(SOCKADDR*)&saRemote,&saRemoteLen,NULL,NULL);
if (Accept == SOCKET_ERROR) {
printf("Accept error/n");
}
//set Per-handle Data
PerHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA));
if (PerHandleData == NULL) {
printf("GlobalAlloc momery error!");
return 0;
}
printf("Socket number %d connected./n ",Accept);
PerHandleData->socket = Accept;
memcpy(&PerHandleData->ClientAddr,&saRemote,saRemoteLen);
//PerHandleData 包含了与套接字相关的其他信息
if ( CreateIoCompletionPort((HANDLE)Accept,hCompletionPort,(DWORD)PerHandleData,0) == NULL ) {
printf("CreateCompletionPort Error!");
return 0;
}
PerIoOperationData = (LPPER_IO_OPERATION_DATA)GlobalAlloc(
GPTR,sizeof(PER_IO_OPERATION_DATA));
ZeroMemory(&(PerIoOperationData->Overlapped),sizeof(OVERLAPPED));
PerIoOperationData->BytesSEND = 0;
PerIoOperationData->BytesRECV = 0;
PerIoOperationData->DataBuf.buf = PerIoOperationData->Buffer;
PerIoOperationData->DataBuf.len = 8192;
Flags = 0;
if (WSARecv(Accept, &(PerIoOperationData->DataBuf), 1, &RecvBytes, &Flags,
&(PerIoOperationData->Overlapped), NULL) == SOCKET_ERROR) {
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() failed with error %d/n", WSAGetLastError());
return;
}
}
}
}
int InitSock(void)
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if (err != 0 ) {
return 0;
}
if (LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 ) {
WSACleanup();
return 0;
}
return 1;
}
DWORD WINAPI SerWorkThread(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)
{
//获得完成端口队列状态,在这里会把IO操作的后的信息传入PerHandleData,PerIoData
if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
(LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == 0)
{
printf("GetQueuedCompletionStatus failed with error %d/n", GetLastError());
return 0;
}
//BytesTransferred在完成一次IO操作后,接受/传输的实际字符数
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;
}
if (PerIoData->BytesRECV == 0)
{
PerIoData->BytesRECV = BytesTransferred;
PerIoData->BytesSEND = 0;
}
else
{
PerIoData->BytesSEND += BytesTransferred;
}
if (PerIoData->BytesRECV > PerIoData->BytesSEND)
{
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;
Flags = 0;
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.len = 8192;
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;
}
}
else
{//将接受到的消息打印出来
printf("%s",&PerIoData->DataBuf);
}
}
}
}