IOCP2.cpp:Defines the entry point for the console application.
//
#include "stdafx.h"
#include <WinSock2.h>
#include <MSWSock.h>
#include <Windows.h>
#include <process.h>
#pragma comment (lib, "Ws2_32.lib")
#define MAX_BUFFER256
#define MAX_TIMEOUT 1000
#define Max_socket 1024
#define MAX_THREAD64
#define MAX_ACCEPT 5
typedef enum _OPERATION_INFO_
{
Op_null,
Op_accept,
Op_read,
Op_write
}operationinfo;
typedef struct _PER_HANDLE_DATA_
{
Public:
_per_handle_data_ ()
{
Clean ();
}
~_per_handle_data_ ()
{
Clean ();
}
Protected:
void Clean ()
{
sock = Invalid_socket;
memset (&addr, 0, sizeof (addr));
Addr.sin_addr. S_un. S_ADDR = Inaddr_any;
Addr.sin_port = htons (0);
addr.sin_family = af_inet;
}
Public:
SOCKET sock;
Sockaddr_in addr;
}perhandledata, *pperhandledata;
typedef struct _PER_IO_DTATA_
{
Public
_per_io_dtata_ ()
{
Clean ();
}
~_per_io_dtata_ ()
{
Clean ();
}
void Clean ()
{
ZeroMemory (&ol, sizeof (OL));
memset (buf, 0, sizeof (BUF));
Saccept = Invalid_socket;
Slisten = Invalid_socket;
Wsabuf.buf = BUF;
Wsabuf.len = Max_buffer;
OpType = Op_null;
}
Public
Wsaoverlapped ol;
SOCKET saccept; Only valid with AcceptEx
SOCKET Slisten; Only valid with AcceptEx
Wsabuf Wsabuf;
Char Buf[max_buffer];
Operationinfo OpType;
}periodata, *pperiodata;
HANDLE Hthread[max_thread] = {0};
periodata* Pacceptdata[max_accept] = {0};
int g_nthread = 0;
BOOL g_bexitthread = FALSE;
Lpfn_acceptex Lpfnacceptex = NULL;
Lpfn_getacceptexsockaddrs Lpfngetacceptexsockaddrs = NULL;
GUID Guidacceptex = Wsaid_acceptex;
GUID Guidgetacceptexsockaddrs = Wsaid_getacceptexsockaddrs;
unsigned __stdcall ThreadProc (LPVOID lParam);
BOOL postaccept (periodata* piodata);
int _tmain (int argc, _tchar* argv[])
{
WORD wversionrequested = Makeword (2, 2);
Wsadata Wsadata;
if (0! = WSAStartup (wversionrequested, &wsadata))
{
printf ("WSAStartup failed with error code:%d/n", GetLastError ());
return exit_failure;
}
if (2! = Hibyte (wsadata.wversion) | | 2! = lobyte (wsadata.wversion))
{
printf ("Socket version not supported./n");
WSACleanup ();
return exit_failure;
}
Create IOCP
HANDLE HIOCP = CreateIoCompletionPort (INVALID_HANDLE_VALUE, NULL, NULL, 0);
if (NULL = = HIOCP)
{
printf ("CreateIoCompletionPort failed with error code:%d/n", WSAGetLastError ());
WSACleanup ();
return exit_failure;
}
Create worker Thread
System_info si = {0};
GetSystemInfo (&SI);
for (int i = 0; i < (int) si.dwnumberofprocessors+2; i++)
{
Hthread[g_nthread] = (HANDLE) _beginthreadex (null, 0, ThreadProc, (LPVOID) HIOCP, 0, NULL);
if (NULL = = Hthread[g_nthread])
{
printf ("_beginthreadex failed with error code:%d/n", GetLastError ());
Continue
}
++g_nthread;
if (G_nthread > Max_thread)
{
Break
}
}
Create Listen SOCKET
SOCKET Slisten = WSASocket (Af_inet, Sock_stream, ipproto_tcp, NULL, 0, wsa_flag_overlapped);
if (Invalid_socket = = Slisten)
{
printf ("WSASocket failed with error code:%d/n", WSAGetLastError ());
Goto Exit_code;
}
Associate SOCKET with IOCP
if (null = = CreateIoCompletionPort ((HANDLE) Slisten, HIOCP, NULL, 0))
{
printf ("CreateIoCompletionPort failed with error code:%d/n", WSAGetLastError ());
if (invalid_socket! = Slisten)
{
Closesocket (Slisten);
Slisten = Invalid_socket;
}
Goto Exit_code;
}
Bind SOCKET
Sockaddr_in addr;
memset (&addr, 0, sizeof (addr));
addr.sin_family = af_inet;
Addr.sin_addr. S_un. S_ADDR = inet_addr ("127.0.0.1");
Addr.sin_port = htons (5050);
if (Socket_error = Bind (Slisten, (lpsockaddr) &addr, sizeof (addr)))
{
printf ("Bind failed with error code:%d/n", WSAGetLastError ());
if (invalid_socket! = Slisten)
{
Closesocket (Slisten);
Slisten = Invalid_socket;
}
Goto Exit_code;
}
Start Listen
if (Socket_error = = Listen (Slisten, 200))
{
printf ("Listen failed with error code:%d/n", WSAGetLastError ());
if (invalid_socket! = Slisten)
{
Closesocket (Slisten);
Slisten = Invalid_socket;
}
Goto Exit_code;
}
printf ("Server start, wait for client to connect .../n");
DWORD dwbytes = 0;
if (Socket_error = = WSAIoctl (Slisten, Sio_get_extension_function_pointer, &guidacceptex, sizeof (GUIDACCEPTEX), &lpfnacceptex,
sizeof (Lpfnacceptex), &dwbytes, NULL, NULL))
{
printf ("WSAIoctl failed with error code:%d/n", WSAGetLastError ());
if (invalid_socket! = Slisten)
{
Closesocket (Slisten);
Slisten = Invalid_socket;
}
Goto Exit_code;
}
if (Socket_error = = WSAIoctl (Slisten, Sio_get_extension_function_pointer, &guidgetacceptexsockaddrs,
sizeof (Guidgetacceptexsockaddrs), &lpfngetacceptexsockaddrs, sizeof (Lpfngetacceptexsockaddrs),
&dwbytes, NULL, NULL))
{
printf ("WSAIoctl failed with error code:%d/n", WSAGetLastError ());
if (invalid_socket! = Slisten)
{
Closesocket (Slisten);
Slisten = Invalid_socket;
}
Goto Exit_code;
}
Post max_accept ACCEPT
for (int i=0; i<max_accept; i++)
{
Pacceptdata[i] = new Periodata;
Pacceptdata[i]->slisten = Slisten;
Postaccept (Pacceptdata[i]);
}
After 1 hour later, Server shutdown.
Sleep (1000 * 60 *60);
Exit_code:
G_bexitthread = TRUE;
PostQueuedCompletionStatus (HIOCP, 0, NULL, NULL);
WaitForMultipleObjects (G_nthread, Hthread, TRUE, INFINITE);
for (int i = 0; i < g_nthread; i++)
{
CloseHandle (Hthread[g_nthread]);
}
for (int i=0; i<max_accept; i++)
{
if (Pacceptdata[i])
{
Delete Pacceptdata[i];
Pacceptdata[i] = NULL;
}
}
if (invalid_socket! = Slisten)
{
Closesocket (Slisten);
Slisten = Invalid_socket;
}
CloseHandle (HIOCP); Close IOCP
WSACleanup ();
return 0;
}
BOOL postaccept (periodata* piodata)
{
if (Invalid_socket = = Piodata->slisten)
{
return FALSE;
}
DWORD dwbytes = 0;
Piodata->optype = op_accept;
Piodata->saccept = WSASocket (Af_inet, Sock_stream, ipproto_tcp, NULL, 0, wsa_flag_overlapped);
if (Invalid_socket = = piodata->saccept)
{
printf ("WSASocket failed with error code:%d/n", WSAGetLastError ());
return FALSE;
}
if (FALSE = = Lpfnacceptex (Piodata->slisten, Piodata->saccept, Piodata->wsabuf.buf, Piodata->wsabuf.len-( (sizeof (SOCKADDR_IN) +16),
sizeof (sockaddr_in) +16, sizeof (sockaddr_in) +16, &dwbytes, & (Piodata->ol)))
{
if (wsa_io_pending! = WSAGetLastError ())
{
printf ("Lpfnacceptex failed with error code:%d/n", WSAGetLastError ());
return FALSE;
}
}
return TRUE;
}
unsigned __stdcall ThreadProc (LPVOID lParam)
{
HANDLE HIOCP = (HANDLE) LParam;
perhandledata* pperhandledata = NULL;
periodata* pperiodata = NULL;
wsaoverlapped* lpoverlapped = NULL;
DWORD Dwtrans = 0;
DWORD dwFlags = 0;
while (!g_bexitthread)
{
BOOL BRet = GetQueuedCompletionStatus (HIOCP, &dwtrans, (pulong_ptr) &pperhandledata, &lpoverlapped, MAX_ TIMEOUT);
if (!bret)
{
Timeout and Exit thread
if (Wait_timeout = = GetLastError ())
{
Continue
}
Error
printf ("GetQueuedCompletionStatus failed with Error:%d/n", GetLastError ());
Continue
}
Else
{
Pperiodata = Containing_record (lpoverlapped, Periodata, OL);
if (NULL = = Pperiodata)
{
Exit thread
Break
}
if ((0 = = Dwtrans) && (op_read = = Pperiodata->optype | | Op_write = = Pperiodata->optype))
{
Client leave.
printf ("Client: <%s:%d> leave./n", Inet_ntoa (PPERHANDLEDATA->ADDR.SIN_ADDR), Ntohs (pperhandledata-> Addr.sin_port));
Closesocket (Pperhandledata->sock);
Delete Pperhandledata;
Delete Pperiodata;
Continue
}
Else
{
Switch (pperiodata->optype)
{
Case op_accept://ACCEPT
{
sockaddr_in* remote = NULL;
sockaddr_in* local = NULL;
int remotelen = sizeof (sockaddr_in);
int locallen = sizeof (sockaddr_in);
Lpfngetacceptexsockaddrs (Pperiodata->wsabuf.buf, Pperiodata->wsabuf.len-((sizeof (sockaddr_in) +16),
sizeof (sockaddr_in) +16, sizeof (sockaddr_in) +16, (lpsockaddr*) &local, &locallen, (lpsockaddr*) &remote, &remotelen);
printf ("Client <%s:%d> come in./n", Inet_ntoa (REMOTE->SIN_ADDR), Ntohs (Remote->sin_port));
printf ("Recv Data: <%s:%d>%s./n", Inet_ntoa (REMOTE->SIN_ADDR), Ntohs (Remote->sin_port), pperiodata-> WSABUF.BUF);
if (NULL! = pperhandledata)
{
Delete Pperhandledata;
Pperhandledata = NULL;
}
Pperhandledata = new Perhandledata;
Pperhandledata->sock = pperiodata->saccept;
perhandledata* pperhandle = new Perhandledata;
Pperhandle->sock = pperiodata->saccept;
periodata* Pperio = new Periodata;
Pperio->optype = Op_write;
strcpy_s (Pperio->buf, Max_buffer, pperiodata->buf);
DWORD Dwtrans = strlen (PPERIO->BUF);
memcpy (& (PPERHANDLEDATA->ADDR), remote, sizeof (SOCKADDR_IN));
Associate with IOCP
if (NULL = = CreateIoCompletionPort ((HANDLE) (Pperhandledata->sock), HIOCP, (ulong_ptr) pperhandledata, 0))
{
printf ("CreateIoCompletionPort failed with error code:%d/n", GetLastError ());
Closesocket (Pperhandledata->sock);
Delete Pperhandledata;
Continue
}
Post Accept
memset (& (Pperiodata->ol), 0, sizeof (Pperiodata->ol));
Postaccept (Pperiodata);
//Post Receive
DWORD dwFlags = 0;
if (Socket_error = = WSASend (Pperhandle->sock, & (Pperio->wsabuf), 1,
&dwtrans, DwFlags, & (pperio- >ol) (NULL))
{
if (wsa_io_pending! = WSAGetLastError ())
{
printf ("WSASend failed with error code:%d/n", WSAGetLastError ());
Closesocket (Pperhandle->sock);
Delete pperhandle;
Delete Pperio;
Continue;
}
}
}
break;
Case Op_read://READ
printf ("Recv client <%s:%d> data:%s/n", Inet_ntoa (PPERHANDLEDATA->ADDR.SIN_ADDR) , Ntohs (Pperhandledata->addr.sin_port), pperiodata->buf);
Pperiodata->optype = Op_write;
memset (& (Pperiodata->ol), 0, sizeof (Pperiodata->ol));
if (socket_error = = WSASend (Pperhandledata->sock, & (Pperiodata->wsabuf), 1, &dwtrans, DwFlags, & (Pperiodata->ol), NULL))
{
if (wsa_io_pending! = WSAGetLastError ())
{
printf ("WSASend failed with Error code:%d./n ", WSAGetLastError ());
Continue;
}
}
break;
Case Op_write://WRITE
{
Pperiodata->optype = Op_read;
dwFlags = 0;
memset (& (Pperiodata->ol), 0, sizeof (Pperiodata->ol));
memset (pperiodata->buf, 0, sizeof (PPERIODATA->BUF));
Pperiodata->wsabuf.buf = pperiodata->buf;
Dwtrans = Pperiodata->wsabuf.len = Max_buffer;
if (Socket_error = = WSARecv (Pperhandledata->sock, & (Pperiodata->wsabuf), 1, &dwtrans, &dwFlags, & (Pperiodata->ol), NULL))
{
if (wsa_io_pending! = WSAGetLastError ())
{
printf ("WSARecv failed with error code:%d./n", WSAGetLastError ());
Continue
}
}
}
Break
Default
Break
}
}
}
}
return 0;
}
Winsock IOCP Model (ii)