Winsock IOCP Model (ii)

Source: Internet
Author: User
Tags htons

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-&GT;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-&GT;SIN_ADDR), Ntohs (Remote->sin_port));
printf ("Recv Data: <%s:%d>%s./n", Inet_ntoa (REMOTE-&GT;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)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.