// IOCP_Server.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "IOCP_Server.h"
#include "Client.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 唯一的应用程序对象
CWinApp theApp;
using namespace std;
#include "Client.h"
#include <afxtempl.h>
#define PORT 12345
HANDLE hComPort = NULL;
DWORD WINAPI ServerWorkerThread(LPVOID pParam);
SOCKET sAccept;
#define THREAD_SLEEP_TIME 100
CObList clientList;
typedef struct _socktnode {
CClient *pClient;
_socktnode* pNext;
}SOCKETNODE, *PSOCKETNODE;
PSOCKETNODE HeaderSocktNode = NULL;
void AddNode(CClient* pClient)
{
clientList.AddTail((CObArray*)pClient);
}
void DeleteNode(CClient* pClient)
{
POSITION pos1 = NULL;
POSITION pos2 = NULL;
for (pos1 = clientList.GetHeadPosition(); (pos2 = pos1) != NULL;)
{
CClient *pClient_temp = (CClient*)clientList.GetNext(pos1);
if (pClient_temp == pClient)
{
clientList.RemoveAt(pos2);
delete pClient_temp;
pClient_temp = NULL;
}
}
}
DWORD WINAPI ServerWorkerThread(LPVOID pParam)
{
if (TRUE)
{
DWORD dwIoSize;
CClient *pClient;
LPOVERLAPPED lpOverlapped;
while (TRUE)
{
dwIoSize = -1;
lpOverlapped = NULL;
pClient = NULL;
BOOL bIoRet = GetQueuedCompletionStatus(
hComPort
, &dwIoSize
, (LPDWORD)&pClient
, &lpOverlapped
, THREAD_SLEEP_TIME
);
if (!bIoRet)
{
DWORD dwIoError = GetLastError();
if (dwIoError == WAIT_TIMEOUT)
{
continue;
}
else if (NULL != lpOverlapped)
{
DeleteNode(pClient);
}
else
{
break;
}
}
else
{
if (0 == dwIoSize)
{
DeleteNode(pClient);
}
PIO_OPERATION_DATA pIO = CONTAINING_RECORD(lpOverlapped, IO_OPERATION_DATA, overlapped);
if (pIO->type == READ)
{
pClient->m_IO.len = dwIoSize;
pClient->Send(pIO->dataBuf.buf, pIO->dataBuf.len);
}
else
{
if (pIO->type == WRITE)
{
pIO->len = 0;
if (pClient->Recv() == FALSE)
{
DeleteObject(pClient);
}
}
}
}
}
}
return 0;
}
int main()
{
int nRetCode = 0;
HMODULE hModule = ::GetModuleHandle(nullptr);
if (hModule != nullptr)
{
// 初始化 MFC 并在失败时显示错误
if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0))
{
// TODO: 更改错误代码以符合您的需要
wprintf(L"错误: MFC 初始化失败\n");
nRetCode = 1;
}
else
{
// TODO: 在此处为应用程序的行为编写代码。
int ret;
WSADATA wsaData;
if ((ret = WSAStartup(0x0202, &wsaData)) != 0)
{
printf("WSAStartup 执行错误%d\n", ret);
return -1;
}
SOCKET sListen;
if ((sListen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("WSASocket()执行错误%d\n", WSAGetLastError());
WSACleanup();
return -1;
}
SOCKADDR_IN InternetAddr;
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InternetAddr.sin_port = htons(PORT);
if (bind(sListen, (PSOCKADDR)&InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
{
printf("bind()执行错误 %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
if (listen(sListen, 5) == SOCKET_ERROR)
{
printf("listen()执行错误 %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
if ((hComPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)) == NULL)
{
printf("CreateIoCompletionPort()执行错误%d\n", WSAGetLastError());
return -1;
}
SYSTEM_INFO SystemInfo;
GetSystemInfo(&SystemInfo);
for (int i = 0; i < SystemInfo.dwNumberOfProcessors * 2; i++)
{
HANDLE hThreadHandle;
DWORD dwThreadID;
if ((hThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ServerWorkerThread, NULL, 0, &dwThreadID)) == NULL)
{
printf("CreateThread错误%d\n", GetLastError());
return -1;
}
CloseHandle(hThreadHandle);
}
while (true)
{
SOCKADDR_IN servAddr;
int serAddrLen = sizeof(servAddr);
if ((sAccept = WSAAccept(sListen, (sockaddr*)&servAddr, &serAddrLen, NULL, 0)) == SOCKET_ERROR)
{
printf("WSAAccept()执行错误%d\n", WSAGetLastError());
break;
}
CClient* pClient = new CClient(sAccept, servAddr);
AddNode(pClient);
if (CreateIoCompletionPort((HANDLE)sAccept, hComPort, (DWORD)pClient, 0) == NULL)
{
return -1;
}
if (!pClient->Recv())
{
DeleteNode(pClient);
}
}
}
}
else
{
// TODO: 更改错误代码以符合您的需要
wprintf(L"错误: GetModuleHandle 失败\n");
nRetCode = 1;
}
return nRetCode;
}