#include<Windows.h>
int main(int argc, char* argv[])
{
SOCKET listener;
SOCKET newsocket;
WSADATA WsaData;
struct sockaddr_in serverAddress;
struct sockaddr_in clientAddress;
int clientAddressLength;
int err;
CheckOsVersion();
err = WSAStartup(0x0101, &WsaData);
if (err == SOCKET_ERROR)
{
FatalError("WSAStartup Failed");
return EXIT_FAILURE;
}
/*open a tcp socket connection to the server by d
default,a socket is alays opened for ouverlapped
I/O.DO NOT attach this socket (listener) to the
I/O completion port!*/
listener = socket(AF_INET, SOCK_STREAM, 0);
if (listener < 0)
{
FatalError("socket() failed");
return EXIT_FAILURE;
}
/*Bind our local address */
memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddress.sin_port = htons(SERV_TCP_PORT);
err = bind(listener, (struct sockaddr*)&serverAddress,
sizeof(serverAddress));
if (err < 0)
FatalError("bind() failed");
ghCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
if (ghCompletionPort == NULL)
{
FatalError("CreateIoCompletionPort() failed");
}
CreateWorkerThreads();
listen(listener, 5);
fprintf(stderr, "Echo Server with I/O Completion Ports\n");
fprintf(stderr, "Running on TCP port %d\n", SERV_TCP_PORT);
fprintf(stderr, "\n Press Ctrl+C to stop the server\n");
//loop forever accepting requests new connections and starting
// reading from them.
for (;;)
{
struct ContextKey *pKey;
clientAddressLength = sizeof(clientAddress);
newsocket = accept(listener, (struct sockaddr*) &clientAddress,
&clientAddressLength);
if (newsocket < 0)
{
FatalError("accept() Failed");
return EXIT_FAILURE;
}
/*Create acontext key and initialize it.
calloc with zero the buffer*/
pKey = calloc(1, sizeof(struct ContextKey));
pKey->sock = newsocket;
pKey->ovOut.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
/*Set the event for writing so that packets will
not be sent to hte completion port when a write finishes.*/
pKey->ovOut.hEvent = (HANDLE)((DWORD)pKey->ovOut.hEvent | 0x1);
//Associate the socket with the completion port
CreateIoCompletionPort((HANDLE)newsocket, ghCompletionPort, (DWORD)pKey, 0);
//kick off the first read
IssueRead(pKey);
}
return 0;
}
#include<Windows.h>
int main(int argc, char* argv[])
{
SOCKET listener;
SOCKET newsocket;
WSADATA WsaData;
struct sockaddr_in serverAddress;
struct sockaddr_in clientAddress;
int clientAddressLength;
int err;
CheckOsVersion();
err = WSAStartup(0x0101, &WsaData);
if (err == SOCKET_ERROR)
{
FatalError("WSAStartup Failed");
return EXIT_FAILURE;
}
/*open a tcp socket connection to the server by d
default,a socket is alays opened for ouverlapped
I/O.DO NOT attach this socket (listener) to the
I/O completion port!*/
listener = socket(AF_INET, SOCK_STREAM, 0);
if (listener < 0)
{
FatalError("socket() failed");
return EXIT_FAILURE;
}
/*Bind our local address */
memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddress.sin_port = htons(SERV_TCP_PORT);
err = bind(listener, (struct sockaddr*)&serverAddress,
sizeof(serverAddress));
if (err < 0)
FatalError("bind() failed");
ghCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
if (ghCompletionPort == NULL)
{
FatalError("CreateIoCompletionPort() failed");
}
CreateWorkerThreads();
listen(listener, 5);
fprintf(stderr, "Echo Server with I/O Completion Ports\n");
fprintf(stderr, "Running on TCP port %d\n", SERV_TCP_PORT);
fprintf(stderr, "\n Press Ctrl+C to stop the server\n");
//loop forever accepting requests new connections and starting
// reading from them.
for (;;)
{
struct ContextKey *pKey;
clientAddressLength = sizeof(clientAddress);
newsocket = accept(listener, (struct sockaddr*) &clientAddress,
&clientAddressLength);
if (newsocket < 0)
{
FatalError("accept() Failed");
return EXIT_FAILURE;
}
/*Create acontext key and initialize it.
calloc with zero the buffer*/
pKey = calloc(1, sizeof(struct ContextKey));
pKey->sock = newsocket;
pKey->ovOut.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
/*Set the event for writing so that packets will
not be sent to hte completion port when a write finishes.*/
pKey->ovOut.hEvent = (HANDLE)((DWORD)pKey->ovOut.hEvent | 0x1);
//Associate the socket with the completion port
CreateIoCompletionPort((HANDLE)newsocket, ghCompletionPort, (DWORD)pKey, 0);
//kick off the first read
IssueRead(pKey);
}
return 0;
}
ECHOSRV.C中的CreateWorkerThreads()
void CreateWorkerThreads()
{
SYSTEM_INFO sysinfo;
DWORD dwThreadId;
DWORD dwThreads;
DWORD i;
GetSystemInfo(&sysinfo);
dwThreads = sysinfo.dwNumberOfProcessors * 2 + 2;
for (i = 0; i < dwThreads; i++)
{
HANDLE hThread;
hThread = CreateThread(NULL, 0, ThreadFunc, NULL, 0, &dwThreadId);
CloseHandle(hThread);
}
}
DWORD WINAPI ThreadFunc(LPVOID pVoid)
{
BOOL bResult;
DWORD dwNumRead;
struct ContextKey *pCntx;
LPOVERLAPPED lpOverlapped;
UNREFERENCED_PARAMETER(pVoid);
/*Loop forever on getting packets from
the I/O completion port*/
for (;;)
{
bResult = GetQueuedCompletionStatus(
ghCompletionPort, &dwNumRead,
&(DWORD)pCntx, &lpOverlapped, INFINITE);
if (bResult == FALSE && lpOverlapped == NULL)
{
FatalError("ThreadFunc -Illegal call to GetQueuedCompletionStatus");
}
else if (bResult == FALSE && lpOverlapped != NULL)
{
//This happens occasionally instead of
//end-of-file,Not sure why.
closesocket(pCntx->sock);
free(pCntx);
fprintf(stderr, "ThreadFunc - I/O operation falied \n");
}
else if (dwNumRead == 0)
{
closesocket(pCntx->sock);
free(pContx);
fprintf(stderr, "ThreadFunc - End of file.\n");
}
//Got a valid data block!
//Save the data to our buffer and write it
//all back out (echo it) if we have see a \n
else
{
//Figure out where in the buffer to save the character
char* pch = &pCntx->OutBuffer[pCntx->nOutBufIndex++];
*pch++ = pCntx->InBuffer[0];
*pch = ‘\0‘;
if (pCntx->InBuffer[0] == ‘\n‘)
{
WriteFile((HANDLE)(pCntx->sock),
pCntx->OutBuffer, pCntx->nOutBufIndex,
&pCntx->dwWritten, &pCntx->ovOut);
pCntx->nOutBufIndex = 0;
fprintf(stderr, "Echo on socket %x.\n",pCntx->sock);
}
//start a new read
IssueRead(pCntx);
}
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。