WSRecv

WSARecv()是从一个套接口接收数据的程序。主要用于在重叠模型中接收数据。

int WSARecv(
  SOCKET s,
  LPWSABUF lpBuffers,
  DWORD dwBufferCount,
  LPDWORD lpNumberOfBytesRecvd,
  LPDWORD lpFlags,
  LPWSAOVERLAPPED lpOverlapped,
  LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

Parameters
s
[in] A descriptor identifying a connected socket.
lpBuffers
[in, out] A pointer to an array of WSABUF structures. Each WSABUF structure contains a pointer to a buffer and the length, in bytes, of the buffer.
dwBufferCount
[in] The number of WSABUF structures in the lpBuffers array.
lpNumberOfBytesRecvd
[out] A pointer to the number, in bytes, received by this call if the receive operation completes immediately. If the lpOverlapped parameter is non-NULL, this parameter is optional and can be set to NULL.
lpFlags
[in, out] A pointer to flags used to modify the behavior of the WSARecv function call.
lpOverlapped
[in] A pointer to a WSAOVERLAPPED structure (ignored for nonoverlapped sockets).
lpCompletionRoutine
[in] A pointer to the completion routine called when the receive operation has been completed (ignored for nonoverlapped sockets).

Return Value
If no error occurs and the receive operation has completed immediately, WSARecv returns zero. In this case, the completion routine will have already been scheduled to be called once the calling thread is in the alertable state. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError. The error code WSA_IO_PENDING indicates that the overlapped operation has been successfully initiated and that completion will be indicated at a later time. Any other error code indicates that the overlapped operation was not successfully initiated and no completion indication will occur.
如果没有发生错误,并且接收操作已经立即完成,则WSARecv返回零。在这种情况下,一旦调用线程处于alertable状态,完成例程将被调度为被调用。否则,将返回SOCKET_ERROR值,并通过调用WSAGetLastError检索特定的错误代码。错误代码WSA_IO_PENDING指示重叠操作已经成功启动,稍后将指示完成。任何其他错误代码都表示没有成功启动重叠操作,也不会出现完成指示。

看实例代码,从代码中窥视其用法:

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>

#pragma warning(disable: 4127)      // Conditional expression is a constant
#pragma comment(lib, "ws2_32.lib") 

#define	 DATA_BUFSIZE 5
#define  MAX_ASYN_IO_BUFF_COUNT 2

/**
@name : 重叠结构,可用于异步IO
*/
struct AsynIoResultImp: public OVERLAPPED
{
	AsynIoResultImp()
	{
		connSocket = INVALID_SOCKET;
		IniBuf();
	}

	// 测试用就不考虑释放了
	void IniBuf()
	{
		for (size_t i = 0; i < MAX_ASYN_IO_BUFF_COUNT; ++i)
		{
			buffList[i].len = DATA_BUFSIZE;
			buffList[i].buf = new  char[DATA_BUFSIZE];
		}
		buffCount = MAX_ASYN_IO_BUFF_COUNT;
		recvBytes = 0;
	}

	SOCKET			  connSocket;
	WSABUF			  buffList[MAX_ASYN_IO_BUFF_COUNT];
	DWORD             buffCount;
	DWORD			  recvBytes;
};


void  main(int argc, char **argv)
{
	WSADATA wsd;
	struct addrinfo *result = NULL, *ptr = NULL, hints = { 0 };
	DWORD Flags;
	int err, rc;

	AsynIoResultImp io;

	// Load Winsock
	rc = WSAStartup(MAKEWORD(2, 2), &wsd);
	if (rc != 0) 
	{
		fprintf(stderr, "Unable to load Winsock: %d\n", rc);
		return;
	}

	// Initialize the hints to retrieve the server address for IPv4
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

 	rc = getaddrinfo("192.168.10.42", "3014", &hints, &result);
 	if (rc != 0) 
 	{
 		fprintf(stderr, "getaddrinfo failed: %d\n", rc);
 		return;
 	}

	for (ptr = result; ptr != NULL; ptr = ptr->ai_next) 
	{
		io.connSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
		if (io.connSocket == INVALID_SOCKET)
		{
			fprintf(stderr, "socket failed: %d\n", WSAGetLastError());
			freeaddrinfo(result);
			return;
		}

		rc = connect(io.connSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
		if (rc == SOCKET_ERROR) 
		{
			if (WSAECONNREFUSED == (err = WSAGetLastError())) 
			{
				closesocket(io.connSocket);
				io.connSocket = INVALID_SOCKET;
				continue;
			}
			fprintf(stderr, "connect failed: %d\n", err);
			freeaddrinfo(result);
			closesocket(io.connSocket);
			return;
		}
		break;
	}
	if (io.connSocket == INVALID_SOCKET)
	{
		fprintf(stderr, "Unable to establish connection with the server!\n");
		freeaddrinfo(result);
		return;
	}

	printf("Client connected...\n");

	// Create an event handle and setup an overlapped structure.
	io.hEvent = WSACreateEvent();
	if (io.hEvent == NULL) {
		fprintf(stderr, "WSACreateEvent failed: %d\n", WSAGetLastError());
		freeaddrinfo(result);
		closesocket(io.connSocket);
		return;
	}

	char data[DATA_BUFSIZE+1] = { 0 };

	// Call WSARecv until the peer closes the connection
	// or until an error occurs
	while (1) 
	{
		io.IniBuf();
		Flags = 0;
		rc = WSARecv(io.connSocket, (LPWSABUF)io.buffList, io.buffCount, &io.recvBytes, &Flags, &io, NULL);
		if ((rc == SOCKET_ERROR) && (WSA_IO_PENDING != (err = WSAGetLastError()))) 
		{
			fprintf(stderr, "WSARecv failed: %d\n", err);
			break;
		}

		rc = WSAWaitForMultipleEvents(1, &io.hEvent, TRUE, INFINITE, TRUE);
		if (rc == WSA_WAIT_FAILED) 
		{
			fprintf(stderr, "WSAWaitForMultipleEvents failed: %d\n", WSAGetLastError());
			break;
		}

		rc = WSAGetOverlappedResult(io.connSocket, &io, &io.recvBytes, FALSE, &Flags);
		if (rc == FALSE) 
		{
			fprintf(stderr, "WSARecv operation failed: %d\n", WSAGetLastError());
			break;
		}

		for (size_t i = 0; i < MAX_ASYN_IO_BUFF_COUNT; ++i)
		{
			size_t len = min(DATA_BUFSIZE, io.recvBytes - i*DATA_BUFSIZE);
			memmove(data, io.buffList[i].buf, len);
			data[len] = '\0';
			printf("Read %d bytes %s\n", io.recvBytes, data);
			if (len != DATA_BUFSIZE) { break; }
		}
	
		WSAResetEvent(io.hEvent);

		// If 0 bytes are received, the connection was closed
		if (io.recvBytes == 0)
			break;
	}

	WSACloseEvent(io.hEvent);
	closesocket(io.connSocket);
	freeaddrinfo(result);

	WSACleanup();

	return;
}

服务器发送数据:1234567890123
收到结果如下:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值