Windows sockets网络开发-重叠IO模型

1、服务器

#pragma once


#include <Windows.h>
#include <WinSock2.h>

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

#define  LISTEN_PORT 5000
#define  BUFFER_SIZE 1024


unsigned long WINAPI client_handler(void* lparam);


int overlapped_io_tcp_server_daemon(){
	
	WSADATA wsd;
	if(WSAStartup(MAKEWORD(2,2), &wsd) != 0){
		printf("error:WSAStartup failed!\n");
		return -1;
	}
	
	SOCKET sock_listen;
	int rc;
	int socket_type = SOCK_STREAM;
	int error_code;
	//create socket
	//sock_listen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	sock_listen = WSASocket(AF_INET, socket_type,0,NULL,0,WSA_FLAG_OVERLAPPED); 
	if(INVALID_SOCKET == sock_listen){
		printf("error:socket failed!\n");
		WSACleanup();
		return -2;
	}
	//set socket address
	sockaddr_in local_addr;
	local_addr.sin_family = AF_INET;
	local_addr.sin_port = htons(LISTEN_PORT);
	local_addr.sin_addr.s_addr = INADDR_ANY;
	//bind
	rc = bind(sock_listen, (struct sockaddr*)&local_addr, sizeof(sockaddr_in));
	if(SOCKET_ERROR == rc){
		printf("error:bind failed!\n");
		closesocket(sock_listen);
		WSACleanup();
		return -3;
	}
	
	//listen
	rc = listen(sock_listen, 5);
	if(SOCKET_ERROR == rc){
		printf("error:listen failed!\n");
		closesocket(sock_listen);
		WSACleanup();
		return -4;
	}

	//while circle
	int total_wsaevent = 0;
	bool is_runnning = true;
	while(is_runnning)
	{
		sockaddr_in remote;
		int remote_len = sizeof(remote);
		//阻塞
		SOCKET sock_conn = accept(sock_listen, (struct sockaddr*)&remote, &remote_len);

		if(INVALID_SOCKET == sock_conn){

			error_code = WSAGetLastError();
			break;
		}

		//if(total_wsaevent > WSA_MAXIMUM_WAIT_EVENTS){
		//	printf("more than WSA_MAXIMUM_WAIT_EVENTS(64)\n");
		//	closesocket(sock_conn);
		//	break;
		//}

		DWORD thread_id;
		CloseHandle(CreateThread(NULL, 0, client_handler, (LPVOID)sock_conn, 0, &thread_id));
		//++total_wsaevent;
	}
	closesocket(sock_listen);
	WSACleanup();
	return 0;
}


unsigned long WINAPI client_handler(void* lparam){

	SOCKET sock_conn = (SOCKET)lparam;
	
	char recv_buffer[BUFFER_SIZE] = {0};
	WSABUF wsa_buf;
	wsa_buf.buf = recv_buffer;
	wsa_buf.len = sizeof(recv_buffer);

	DWORD NoBR;
	DWORD flags=0;
	int error_code = -1;
	DWORD rc;

	WSAEVENT wsa_event = WSACreateEvent();

	WSAOVERLAPPED wsa_overlapped;
	ZeroMemory(&wsa_overlapped, sizeof(wsa_overlapped));
	wsa_overlapped.hEvent = wsa_event;

	HANDLE wait_event[1];
	wait_event[0] = wsa_event;

	while(1){

		ZeroMemory(&wsa_overlapped, sizeof(wsa_overlapped));
		wsa_overlapped.hEvent = wsa_event;

		int recv_len = WSARecv(sock_conn, &wsa_buf, 1,&NoBR ,&flags, &wsa_overlapped,NULL);
		if (SOCKET_ERROR == recv_len){
			error_code = WSAGetLastError();
			if (WSA_IO_PENDING != error_code)
			{
				closesocket(sock_conn);
				WSACloseEvent(wsa_event);
				
				return error_code;
			}
		}
		
		//wait for
		rc = WaitForMultipleObjects(1, wait_event, TRUE, INFINITE);
		if (WSA_WAIT_FAILED == rc || WSA_WAIT_TIMEOUT == rc)
		{
			closesocket(sock_conn);
			WSACloseEvent(wsa_event);
			
			return rc;
		}
		else if (WAIT_OBJECT_0 + 1 == rc)
		{
			//exit event;
			closesocket(sock_conn);
			WSACloseEvent(wsa_event);
			
			return rc;
		}
		//WAIT_OBJECT_0
		// WSAGetOverlappedResult
		DWORD transfered_len = 0;
		if (WSAGetOverlappedResult(sock_conn, &wsa_overlapped, &transfered_len, FALSE, &flags) == FALSE)
		{
			error_code = WSAGetLastError();
			closesocket(sock_conn);
			WSACloseEvent(wsa_event);
			
			return error_code;
		}

		if (transfered_len == 0) //peer closed
		{
			error_code = WSAGetLastError();
			closesocket(sock_conn);
			WSACloseEvent(wsa_event);
			return error_code;
			//continue;
		}
		//handle data from client
		int ret = send(sock_conn, wsa_buf.buf, transfered_len, 0);
		if(SOCKET_ERROR == ret){
			printf("echo send failed!\n");
			closesocket(sock_conn);
			WSACloseEvent(wsa_event);
			return -1;
		}
		printf("echo client\n");

		WSAResetEvent(wsa_event);

	}//while
	
	closesocket(sock_conn);
	WSACloseEvent(wsa_event);
	return 0;
}

2、客户端

#pragma once

#include <Windows.h>
#include <WinSock2.h>
#include <vector>
#include <iostream>

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

#define  LISTEN_PORT 5000
#define  BUFFER_SIZE 1024
#define  MSG_HEAD_TAG  "C2SV"

typedef struct st_MessageHead
{
	char  msg_tag[4];
	DWORD option;
	DWORD content_length;
}MessageHead,*PMessageHead;


int overlapped_io_tcp_client_daemon(const std::string &server_ip, unsigned short server_port, const std::string& content_data)
{

	WSADATA wsd;
	if(WSAStartup(MAKEWORD(2,2),&wsd) !=0){
		printf("error:WSAStartup failed!\n");
		return -1;
	}

	int socket_type = SOCK_STREAM;
	sockaddr_in	server_sockaddr;
	SOCKET sock_conn;
	char recv_buffer[BUFFER_SIZE] = {0};
	WSABUF wsabuf;
	wsabuf.buf=recv_buffer;
	wsabuf.len=sizeof(recv_buffer);
	DWORD NoBR;
	DWORD flags=0;
	int error_code = -1;

	//create wsa_event
	WSAEVENT wsa_event = WSACreateEvent();
	if (WSA_INVALID_EVENT == wsa_event){
		error_code = WSAGetLastError();
		WSACleanup();
		return error_code;
	}

	HANDLE hEvents[1];
	hEvents[0] = wsa_event;

	WSAOVERLAPPED wsa_overlappped;
	ZeroMemory(&wsa_overlappped, sizeof(wsa_overlappped));
	wsa_overlappped.hEvent = wsa_event;

	//start up socket
	server_sockaddr.sin_addr.s_addr = inet_addr(server_ip.c_str());   
	server_sockaddr.sin_family = AF_INET;
	server_sockaddr.sin_port = htons(server_port);//

	//startup wsasocket
	sock_conn = WSASocket(AF_INET, socket_type,0, NULL, 0, WSA_FLAG_OVERLAPPED );
	if (INVALID_SOCKET == sock_conn)
	{
		error_code = WSAGetLastError();
		WSACloseEvent(wsa_event);
		WSACleanup();
		return error_code;
	}

	//connect
	if (connect(sock_conn,(SOCKADDR*)&server_sockaddr,sizeof(server_sockaddr)) == SOCKET_ERROR)
	{
		error_code = WSAGetLastError();
		closesocket(sock_conn);
		WSACloseEvent(wsa_event);
		WSACleanup();
		return error_code;
	}

	//客户端不停地向服务器发送测试数据
	while (1)
	{
		//construct message head
		MessageHead msg_head;
		memcpy(msg_head.msg_tag, MSG_HEAD_TAG, 4);
		msg_head.option = 0;
		msg_head.content_length = (DWORD)content_data.size();
		//total length 
		int total_send_length = (int) (sizeof(MessageHead) + content_data.size());
		std::vector<char> send_buffer;
		send_buffer.reserve(total_send_length);
		send_buffer.assign(total_send_length, 0);
		//fill send_buffer
		char *postion = &send_buffer[0];
		memcpy(postion, &msg_head, sizeof(msg_head));
		memcpy(postion + sizeof(msg_head), content_data.c_str(), content_data.size());
		int left_len = total_send_length;
		int sent_len = 0;

		while(left_len > 0){

			sent_len = send(sock_conn, postion, left_len, 0);

			if (SOCKET_ERROR == sent_len){
				error_code = WSAGetLastError();
				closesocket(sock_conn);
				WSACloseEvent(wsa_event);
				WSACleanup();
				return error_code;
			}
			left_len = total_send_length - sent_len;
			postion+=sent_len;
		}

		//recv
		ZeroMemory(&wsa_overlappped, sizeof(wsa_overlappped));
		wsa_overlappped.hEvent = wsa_event;
		int recv_len = WSARecv(sock_conn, &wsabuf, 1,&NoBR ,&flags, &wsa_overlappped,NULL);
		if (SOCKET_ERROR == recv_len)
		{
			error_code = WSAGetLastError();
			if (WSA_IO_PENDING != error_code)
			{
				closesocket(sock_conn);
				WSACloseEvent(wsa_event);
				WSACleanup();
				return error_code;
			}
		}

		//WaitForMultipleObjects
		DWORD rc = WaitForMultipleObjects(1,hEvents, FALSE, 15*1000 );
		if (WSA_WAIT_FAILED == rc || WSA_WAIT_TIMEOUT == rc)
		{
			closesocket(sock_conn);
			WSACloseEvent(wsa_event);
			WSACleanup();
			return rc;
		}
		else if (WAIT_OBJECT_0 + 1 == rc)
		{
			//exit event;
			closesocket(sock_conn);
			WSACloseEvent(wsa_event);
			WSACleanup();
			return rc;
		}

		// WSAGetOverlappedResult
		DWORD transfered_len = 0;
		if (WSAGetOverlappedResult(sock_conn, &wsa_overlappped, &transfered_len, FALSE, &flags) == FALSE)
		{
			error_code = WSAGetLastError();
			closesocket(sock_conn);
			WSACloseEvent(wsa_event);
			WSACleanup();
			return error_code;
		}

		//closesocket(sock_conn);
		//WSACloseEvent(wsa_event);

		if (transfered_len == 0) //peer closed
		{
			error_code = WSAGetLastError();
			WSACleanup();
			return error_code;
		}

		//recv response
		if (_strnicmp(recv_buffer,MSG_HEAD_TAG,strlen(MSG_HEAD_TAG))==0){

			MessageHead *msg_head = (MessageHead*)recv_buffer;
			const char  *recv_content_ptr = recv_buffer + sizeof(MessageHead);
			std::string recv_content_data(recv_content_ptr, msg_head->content_length);
			std::cout<<"recv from server:"<<recv_content_data.c_str()<<std::endl;
		}

		WSAResetEvent(wsa_event);
		Sleep(1000);
	}



	closesocket(sock_conn);
	WSACloseEvent(wsa_event);

	WSACleanup();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值