ECHOSRV.C中的main()设立一个 I/O completion port

本文详细介绍了如何使用IO完成端口和多线程技术来构建一个高效的TCP回声服务器,包括初始化环境、创建监听套接字、绑定本地地址、设置I/O完成端口、接受新连接以及处理读写操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值