winsock IO模型 重叠端口



用事件通知方式实现的重叠I/O模型

#include <winsock2.h>

#include <stdio.h>

#define PORT    5150

#define MSGSIZE 1024

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

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);

void Cleanup(int);

int main()

{

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_addr.S_un.S_addr = htonl(INADDR_ANY);

local.sin_family = AF_INET;

local.sin_port = htons(PORT);

bind(sListen, (struct 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, (struct sockaddr *)&client, &iaddrSize);  

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

    g_CliSocketArr[g_iTotalConn] = sClient;         // Allocate 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 received  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; }

这个模型与上述其他模型不同的是它使用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异步操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值