您的位置:首页 > 其它

windows重叠模式

2015-12-23 15:52 155 查看
1.WSASocket介绍

SOCKET WSASocket (

  int af, 

  int type, 

  int protocol, 

  LPWSAPROTOCOL_INFO lpProtocolInfo, 

  GROUP g, 

  DWORD dwFlags 

  );

af:只支持AF_INET;

type:新套接口的类型描述。SOCK_STREAM tcp,SOCK_DGRAM udp。

lpProtocolInfo:一个指向PROTOCOL_INFO结构的指针,该结构定义所创建套接口的特性。如果本参数非零,则前三个参数(af, type, protocol)被忽略。

dwFlags :套接口属性描述

2.重叠IO创建

重叠的数据结构(WSAOVERLAPPED),一次投递一个或多个 Winsock I/O 请求。

创建套接字重叠IO套接字

SOCKET s=WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);

win上使用socket创建socket默认设置WSA_FLAG_OVERLAPPED标志

3.重叠IO使用

 WSASend             // sends data on a connected socket. 提供一个指向已填充的数据缓冲区的指针。

 WSASendTo        // sends data to a specific destination, using overlapped I/O where applicable.

 WSARecv        // receives data from a connected socket.

 WSARecvFrom      //receives data on a socket and stores the source address.  提供存放接收数据的缓冲区

 WSAIoctl      //allows for miscellaneous control of a socket.   还可以使用重叠I/O操作的延迟完成特性。

 AcceptEx   //accepts a new connection, returns the local and remote address, and receives the first block of data sent by the client application.

 TrnasmitFile   //transmits file data over a connected socket handle. uses the operating system's cache manager to retrieve the file data, and provides high-performance file data transfer over sockets.

这里面WS_IO_PENDING 是最常见的返回值,这是说明我们的重叠函数调用成功了,但是I/O操作还没有完成。

如果和一个WSAOVERLAPPED结构一起来调用这些函数,那么函数会立即完成并返回,无论套接字是否是阻塞模式。判断I/O请求是否成功的方法有两个,分别是:

1、等待   事件对象通知。

2、通过 完成例程。

4.实例

#include "stdafx.h"
#include <stdio.h>
#include <afx.h>
#include <winsock2.h>

#define  DATA_BUFSIZE 1024

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
SOCKET	ListenSocket,AcceptSocket;
WSAOVERLAPPED	AcceptOverlapped;
WSABUF	DataBuf;
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2),&wsaData);

ListenSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//创建TCP套接字

SOCKADDR_IN ServerAddr;//分配端口及协议族并绑定
ServerAddr.sin_family=AF_INET;
ServerAddr.sin_addr.S_un.S_addr =htonl(INADDR_ANY);
ServerAddr.sin_port=htons(8888);

bind(ListenSocket,(LPSOCKADDR)&ServerAddr, sizeof(ServerAddr));//绑定套接字

listen(ListenSocket, 5);

SOCKADDR_IN ClientAddr;// 定义一个客户端得地址结构作为参数
int addr_length=sizeof(ClientAddr);

WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];
DWORD    dwEventTotal = 0,
dwRecvBytes = 0,
Flags = 0;

AcceptSocket = accept(ListenSocket,(SOCKADDR*)&ClientAddr, &addr_length);
LPCTSTR lpIP = inet_ntoa(ClientAddr.sin_addr);// IP
UINT nPort = ClientAddr.sin_port;// Port

//为接受的套接字创建一个WSAOVERLAPPED结构,并给这个结构分配一个事件对象句柄,同时将该事件对象句柄分配给一个事件数组,以便稍后WSAWaitForMultipleEvents函数使用
EventArray[dwEventTotal] = WSACreateEvent();

ZeroMemory(&AcceptOverlapped, sizeof(WSAOVERLAPPED));
AcceptOverlapped.hEvent = EventArray[dwEventTotal];

char buffer[DATA_BUFSIZE];
ZeroMemory(buffer, DATA_BUFSIZE);
DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer;
dwEventTotal ++;

if(WSARecv(AcceptSocket ,(WSABUF *)&DataBuf,1,&dwRecvBytes,&Flags,&AcceptOverlapped,NULL) == SOCKET_ERROR)
{
if(WSAGetLastError() != WSA_IO_PENDING)
{
closesocket(AcceptSocket);
WSACloseEvent(EventArray[dwEventTotal]);
}
}

while(1)
{
DWORD dwIndex;
dwIndex = WSAWaitForMultipleEvents(dwEventTotal, EventArray ,FALSE ,WSA_INFINITE,FALSE);
// 注意这里返回的Index并非是事件在数组里的Index,而是需要减去WSA_WAIT_EVENT_0
dwIndex = dwIndex - WSA_WAIT_EVENT_0;

WSAResetEvent(EventArray[dwIndex]);

if(WSARecv(AcceptSocket ,&DataBuf,1,&dwRecvBytes,&Flags,&AcceptOverlapped, NULL) == SOCKET_ERROR)
{
if(WSAGetLastError() != WSA_IO_PENDING)
{
closesocket(AcceptSocket);
WSACloseEvent(EventArray[dwEventTotal]);
}
TRACE("dwRecvBytes = %2d\n",dwRecvBytes);
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: