windows重叠模式

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


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值