// my_iocp.cpp
#include <WinSock2.h>
#include <process.h>
#include <iostream>
using namespace std;
#pragma comment (lib, "ws2_32")
typedef struct
{
SOCKET socket;
}PER_HANDLE_DATA, *LPPER_HANDLE_DATA;
const int DATA_BUF_SIZE = 9000;
typedef struct
{
OVERLAPPED overlapped;
WSABUF dataBuf;
char buf[DATA_BUF_SIZE];
DWORD dwSend;
DWORD dwRecv;
}PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;
unsigned __stdcall SerWorkThread(void *param);
const char IP[] = "127.0.0.1";
const unsigned short PORT = 5150;
int main()
{
SOCKET fdSock = INVALID_SOCKET;
sockaddr_in serAddr = {0};
HANDLE hIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0);
if (hIocp == NULL)
{
cout << "CreateIoCompletionPort error " << GetLastError() << endl;
return -1;
}
SYSTEM_INFO sysInfo = {0};
GetSystemInfo(&sysInfo);
for (unsigned int i = 0; i < sysInfo.dwNumberOfProcessors; i++)
{
unsigned int uiThreadId = 0;
HANDLE handle = (HANDLE)_beginthreadex(NULL, 0, SerWorkThread, hIocp, 0, &uiThreadId);
if (handle == NULL)
{
return -1;
}
CloseHandle(handle);
}
WSAData wsaData = {0};
WSAStartup(0x0202, &wsaData);
if (wsaData.wVersion != 0x0202)
{
cout << "not support socket 0x0202 lib." << endl;
goto clear;
}
fdSock = socket(AF_INET, SOCK_STREAM, 0);
if (fdSock == INVALID_SOCKET)
{
goto clear;
}
serAddr.sin_family = PF_INET;
serAddr.sin_addr.s_addr = inet_addr(IP);
serAddr.sin_port = htons(PORT);
if (SOCKET_ERROR == bind(fdSock, reinterpret_cast<sockaddr *>(&serAddr), sizeof(sockaddr_in)))
{
goto clear;
}
if (SOCKET_ERROR == listen(fdSock, 10))
{
goto clear;
}
while (true)
{
LPPER_HANDLE_DATA pPerHandleData = NULL;
LPPER_IO_OPERATION_DATA pPerIoData = NULL;
DWORD dwFlag = 0;
DWORD dwRecved = 0;
sockaddr_in cliAddr = {0};
int iAddrlen = sizeof(sockaddr_in);
SOCKET cliSock = accept(fdSock, reinterpret_cast<sockaddr*>(&cliAddr), &iAddrlen);
if (INVALID_SOCKET == cliSock)
{
cout << "accept error code " << WSAGetLastError() << endl;
goto clear;
}
pPerHandleData = new PER_HANDLE_DATA;
pPerHandleData->socket = cliSock;
if (NULL == CreateIoCompletionPort(reinterpret_cast<HANDLE>(cliSock), hIocp, reinterpret_cast<ULONG_PTR>(pPerHandleData), 0))
{
goto clear;
}
pPerIoData = new PER_IO_OPERATION_DATA;
memset(pPerIoData, 0, sizeof(PER_IO_OPERATION_DATA));
pPerIoData->dwRecv = 0;
pPerIoData->dwSend = 0;
pPerIoData->dataBuf.buf = pPerIoData->buf;
pPerIoData->dataBuf.len = DATA_BUF_SIZE;
if (SOCKET_ERROR == WSARecv(cliSock, &pPerIoData->dataBuf, 1, &dwRecved, &dwFlag, &pPerIoData->overlapped, NULL))
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
cout << "WSARecv error code: " << WSAGetLastError() << endl;
goto clear;
}
}
//memset(&pPerIoData->overlapped, 0, sizeof(pPerIoData->overlapped));
//pPerIoData->dataBuf.len = sizeof("hello world!");
//pPerIoData->dataBuf.buf = pPerIoData->buf;
//strcpy_s(pPerIoData->buf, DATA_BUF_SIZE, "hello world!");
//if (SOCKET_ERROR == WSASend(cliSock, &pPerIoData->dataBuf, 1, &dwRecved, 0, &pPerIoData->overlapped, NULL))
//{
// if (WSAGetLastError() != WSA_IO_PENDING)
// {
// cout << "WSARecv error " << WSAGetLastError() << endl;
// return 0;
// }
//}
cout << "client " << cliSock << " connected." << endl;
}
clear:
WSACleanup();
if (fdSock != INVALID_SOCKET)
{
closesocket(fdSock);
fdSock = INVALID_SOCKET;
}
return 0;
}
unsigned __stdcall SerWorkThread(void *param)
{
if (param == NULL)
{
return 0;
}
DWORD dwFlag = 0;
DWORD dwRecved = 0;
DWORD dwBytesTransferred = 0;
LPPER_HANDLE_DATA pPerHandle = NULL;
LPPER_IO_OPERATION_DATA pPerIoData = NULL;
HANDLE hIocp = reinterpret_cast<HANDLE>(param);
while (true)
{
dwBytesTransferred = 0;
if (FALSE == GetQueuedCompletionStatus(hIocp, &dwBytesTransferred, reinterpret_cast<PULONG_PTR>(&pPerHandle), reinterpret_cast<LPOVERLAPPED*>(&pPerIoData), INFINITE))
{
cout << "GetQueuedCompletionStatus error " << WSAGetLastError() << endl;
if (pPerHandle != NULL)
{
closesocket(pPerHandle->socket);
delete pPerHandle;
pPerHandle = NULL;
}
if (pPerIoData != NULL)
{
delete pPerIoData;
pPerIoData = NULL;
}
continue;
}
if (dwBytesTransferred == 0)
{
cout << "disconnect from client " << pPerHandle->socket << "." << endl;
if (pPerHandle != NULL)
{
closesocket(pPerHandle->socket);
delete pPerHandle;
pPerHandle = NULL;
}
if (pPerIoData != NULL)
{
delete pPerIoData;
pPerIoData = NULL;
}
continue;
}
else
{
if (pPerIoData == NULL || pPerHandle == NULL)
{
return 0;
}
cout << pPerHandle->socket << " len :" << dwBytesTransferred << " recv : " << pPerIoData->dataBuf.buf << endl;
dwFlag = 0;
memset(&pPerIoData->overlapped, 0, sizeof(pPerIoData->overlapped));
pPerIoData->dataBuf.buf = pPerIoData->buf;
pPerIoData->dataBuf.len = DATA_BUF_SIZE;
if (SOCKET_ERROR == WSARecv(pPerHandle->socket, &pPerIoData->dataBuf, 1, &dwRecved, &dwFlag, &pPerIoData->overlapped, NULL))
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
cout << "WSARecv error " << WSAGetLastError() << endl;
if (pPerHandle != NULL)
{
closesocket(pPerHandle->socket);
delete pPerHandle;
pPerHandle = NULL;
}
if (pPerIoData != NULL)
{
delete pPerIoData;
pPerIoData = NULL;
}
continue;;
}
}
//memset(&pPerIoData->overlapped, 0, sizeof(pPerIoData->overlapped));
//pPerIoData->dataBuf.len = dwBytesTransferred;
//pPerIoData->dataBuf.buf = pPerIoData->buf;
//strcpy_s(pPerIoData->buf, DATA_BUF_SIZE, "hello world!");
//if (SOCKET_ERROR == WSASend(pPerHandle->socket, &pPerIoData->dataBuf, 1, &dwRecved, 0, &pPerIoData->overlapped, NULL))
//{
// if (WSAGetLastError() != WSA_IO_PENDING)
// {
// cout << "WSARecv error " << WSAGetLastError() << endl;
// continue;
// }
//}
memset(pPerIoData->dataBuf.buf, 0, pPerIoData->dataBuf.len);
}
}
return 0;
}
iocp 完成端口模型
最新推荐文章于 2023-05-08 21:51:10 发布