您的位置:首页 > 移动开发

Socket I/O模型之重叠I/O(overlapped I/O)--事件通知

2012-05-04 11:19 501 查看
C++代码

// write by larry

// 2009-8-20

// This is a server using overlapped IO(event notify).

#include "stdafx.h"

#include <WINSOCK2.H>

#include <stdio.h>

#pragma comment(lib, "ws2_32.lib")

#define PORT 5150

#define MSGSIZE 1024

typedef struct

{

WSAOVERLAPPED overlap;

WSABUF Buffer;

char szMessage[MSGSIZE];

DWORD NumberOfBytesRecvd;

DWORD Flags;

} PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;

int g_iTotalConn = 0;

SOCKET g_CliSocketArr[MAXIMUM_WAIT_OBJECTS];

WSAEVENT g_CliEventArr[MAXIMUM_WAIT_OBJECTS];

LPPER_IO_OPERATION_DATA g_pPerIoDataArr[MAXIMUM_WAIT_OBJECTS];

DWORD WINAPI WorkerThread(LPVOID lpParam);

void Cleanup(int index);

int main(int argc, char* argv[])

{

WSADATA wsaData;

SOCKET sListen, sClient;

SOCKADDR_IN local, client;

DWORD dwThreadId;

int iAddrSize = sizeof(SOCKADDR_IN);

// Initialize windows socket library

WSAStartup(0x0202, &wsaData);

// Create listening socket

sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

// Bind

local.sin_family = AF_INET;

local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

local.sin_port = htons(PORT);

bind(sListen, (sockaddr*)&local, sizeof(SOCKADDR_IN));

// Listen

listen(sListen, 3);

// Create worker thread

CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId);

while (TRUE)

{

// Accept a connection

sClient = accept(sListen, (sockaddr*)&client, &iAddrSize);

printf("Accepted client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));

g_CliSocketArr[g_iTotalConn] = sClient;

// Associate a PER_IO_OPERATION_DATA structure

g_pPerIoDataArr[g_iTotalConn] = (LPPER_IO_OPERATION_DATA)HeapAlloc(

GetProcessHeap(),

HEAP_ZERO_MEMORY,

sizeof(PER_IO_OPERATION_DATA));

g_pPerIoDataArr[g_iTotalConn]->Buffer.len = MSGSIZE;

g_pPerIoDataArr[g_iTotalConn]->Buffer.buf = g_pPerIoDataArr[g_iTotalConn]->szMessage;

g_CliEventArr[g_iTotalConn] = g_pPerIoDataArr[g_iTotalConn]->overlap.hEvent = WSACreateEvent();

// Launch an asynchronous operation

WSARecv(g_CliSocketArr[g_iTotalConn],

&g_pPerIoDataArr[g_iTotalConn]->Buffer,

1,

&g_pPerIoDataArr[g_iTotalConn]->NumberOfBytesRecvd,

&g_pPerIoDataArr[g_iTotalConn]->Flags,

&g_pPerIoDataArr[g_iTotalConn]->overlap,

NULL);

g_iTotalConn++;

}

closesocket(sListen);

WSACleanup();

return 0;

}

DWORD WINAPI WorkerThread(LPVOID lpParam)

{

int ret, index;

DWORD cbTransferred;

while (TRUE)

{

ret = WSAWaitForMultipleEvents(g_iTotalConn, g_CliEventArr, FALSE, 1000, FALSE);

if (ret == WSA_WAIT_FAILED || ret == WSA_WAIT_TIMEOUT)

{

continue;

}

index = ret - WSA_WAIT_EVENT_0;

WSAResetEvent(g_CliEventArr[index]);

WSAGetOverlappedResult(g_CliSocketArr[index],

&g_pPerIoDataArr[index]->overlap,

&cbTransferred,

TRUE,

&g_pPerIoDataArr[g_iTotalConn]->Flags);

if (cbTransferred == 0)

{

// The connection was closed by client

Cleanup(index);

}

else

{

// g_pPerIoDataArr[index]->szMessage contains the recvived data

g_pPerIoDataArr[index]->szMessage[cbTransferred] = '\0';

send(g_CliSocketArr[index], g_pPerIoDataArr[index]->szMessage, cbTransferred, 0);

// Launch another asynchronous operation

WSARecv(g_CliSocketArr[index],

&g_pPerIoDataArr[index]->Buffer,

1,

&g_pPerIoDataArr[index]->NumberOfBytesRecvd,

&g_pPerIoDataArr[index]->Flags,

&g_pPerIoDataArr[index]->overlap,

NULL);

}

}

return 0;

}

void Cleanup(int index)

{

closesocket(g_CliSocketArr[index]);

WSACloseEvent(g_CliEventArr[index]);

HeapFree(GetProcessHeap(), 0, g_pPerIoDataArr[index]);

if (index < g_iTotalConn-1)

{

g_CliSocketArr[index] = g_CliSocketArr[g_iTotalConn-1];

g_CliEventArr[index] = g_CliEventArr[g_iTotalConn-1];

g_pPerIoDataArr[index] = g_pPerIoDataArr[g_iTotalConn-1];

}

g_pPerIoDataArr[--g_iTotalConn] = NULL;

}

// writeby larry

//2009-8-20

// Thisis a server using overlapped IO(event notify).

#include"stdafx.h"

#include<WINSOCK2.H>

#include<stdio.h>

#pragmacomment(lib, "ws2_32.lib")

#definePORT 5150

#defineMSGSIZE 1024

typedefstruct

{

WSAOVERLAPPED overlap;

WSABUF Buffer;

char szMessage[MSGSIZE];

DWORD NumberOfBytesRecvd;

DWORD Flags;

}PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;

int g_iTotalConn = 0;

SOCKET g_CliSocketArr[MAXIMUM_WAIT_OBJECTS];

WSAEVENT g_CliEventArr[MAXIMUM_WAIT_OBJECTS];

LPPER_IO_OPERATION_DATAg_pPerIoDataArr[MAXIMUM_WAIT_OBJECTS];

DWORDWINAPI WorkerThread(LPVOID lpParam);

voidCleanup(int index);

intmain(int argc, char* argv[])

{

WSADATA wsaData;

SOCKET sListen, sClient;

SOCKADDR_IN local, client;

DWORD dwThreadId;

int iAddrSize = sizeof(SOCKADDR_IN);

// Initialize windows socket library

WSAStartup(0x0202, &wsaData);

// Create listening socket

sListen = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);

// Bind

local.sin_family = AF_INET;

local.sin_addr.S_un.S_addr =htonl(INADDR_ANY);

local.sin_port = htons(PORT);

bind(sListen, (sockaddr*)&local,sizeof(SOCKADDR_IN));

// Listen

listen(sListen, 3);

// Create worker thread

CreateThread(NULL, 0, WorkerThread, NULL, 0,&dwThreadId);

while (TRUE)

{

// Accept a connection

sClient = accept(sListen,(sockaddr*)&client, &iAddrSize);

printf("Acceptedclient:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));

g_CliSocketArr[g_iTotalConn] = sClient;

// Associate a PER_IO_OPERATION_DATAstructure

g_pPerIoDataArr[g_iTotalConn] =(LPPER_IO_OPERATION_DATA)HeapAlloc(

GetProcessHeap(),

HEAP_ZERO_MEMORY,

sizeof(PER_IO_OPERATION_DATA));

g_pPerIoDataArr[g_iTotalConn]->Buffer.len= MSGSIZE;

g_pPerIoDataArr[g_iTotalConn]->Buffer.buf= g_pPerIoDataArr[g_iTotalConn]->szMessage;

g_CliEventArr[g_iTotalConn] =g_pPerIoDataArr[g_iTotalConn]->overlap.hEvent = WSACreateEvent();

// Launch an asynchronous operation

WSARecv(g_CliSocketArr[g_iTotalConn],

&g_pPerIoDataArr[g_iTotalConn]->Buffer,

1,

&g_pPerIoDataArr[g_iTotalConn]->NumberOfBytesRecvd,

&g_pPerIoDataArr[g_iTotalConn]->Flags,

&g_pPerIoDataArr[g_iTotalConn]->overlap,

NULL);

g_iTotalConn++;

}

closesocket(sListen);

WSACleanup();

return 0;

}

DWORDWINAPI WorkerThread(LPVOID lpParam)

{

int ret, index;

DWORD cbTransferred;

while (TRUE)

{

ret = WSAWaitForMultipleEvents(g_iTotalConn,g_CliEventArr, FALSE, 1000, FALSE);

if (ret == WSA_WAIT_FAILED || ret ==WSA_WAIT_TIMEOUT)

{

continue;

}

index = ret - WSA_WAIT_EVENT_0;

WSAResetEvent(g_CliEventArr[index]);

WSAGetOverlappedResult(g_CliSocketArr[index],

&g_pPerIoDataArr[index]->overlap,

&cbTransferred,

TRUE,

&g_pPerIoDataArr[g_iTotalConn]->Flags);

if (cbTransferred == 0)

{

// The connection was closed by client

Cleanup(index);

}

else

{

// g_pPerIoDataArr[index]->szMessagecontains the recvived data

g_pPerIoDataArr[index]->szMessage[cbTransferred]= '\0';

send(g_CliSocketArr[index],g_pPerIoDataArr[index]->szMessage, cbTransferred, 0);

// Launch another asynchronousoperation

WSARecv(g_CliSocketArr[index],

&g_pPerIoDataArr[index]->Buffer,

1,

&g_pPerIoDataArr[index]->NumberOfBytesRecvd,

&g_pPerIoDataArr[index]->Flags,

&g_pPerIoDataArr[index]->overlap,

NULL);

}

}

return 0;

}

voidCleanup(int index)

{

closesocket(g_CliSocketArr[index]);

WSACloseEvent(g_CliEventArr[index]);

HeapFree(GetProcessHeap(), 0,g_pPerIoDataArr[index]);

if (index < g_iTotalConn-1)

{

g_CliSocketArr[index] =g_CliSocketArr[g_iTotalConn-1];

g_CliEventArr[index] =g_CliEventArr[g_iTotalConn-1];

g_pPerIoDataArr[index] =g_pPerIoDataArr[g_iTotalConn-1];

}

g_pPerIoDataArr[--g_iTotalConn] = NULL;

}

这个模型与上述其他模型不同的是它使用Winsock2提供的异步I/O函数WSARecv。在调用WSARecv时,指定一个 WSAOVERLAPPED 结构,这个调用不是阻塞的,也就是说,它会立刻返回。一旦有数据到达的时候,被指定的WSAOVERLAPPED结构中的hEvent被 Signaled。由于下面这个语句

g_CliEventArr[g_iTotalConn] =g_pPerIODataArr[g_iTotalConn]->overlap.hEvent;

使得与该套接字相关联的WSAEVENT对象也被Signaled,所以WSAWaitForMultipleEvents的调用操作成功返回。我们现在应该做的就是用与调用WSARecv相同的WSAOVERLAPPED结构为参数调用WSAGetOverlappedResult,从而得到本次I/O 传送的字节数等相关信息。在取得接收的数据后,把数据原封不动的发送到客户端,然后重新激活一个WSARecv异步操作。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: