完成端口Accept方式

文章一:http://baike.soso.com/v5865322.htm

http://wenku.baidu.com/view/17eb0c2f0066f5335a812136.html

 

文章二:

http://kevensnowgirl.blog.hexun.com/6811572_d.html

http://xingzhesun.blogbus.com/c1584116/

客户端代码

 

// Client.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <WinSock2.h>
#include <stdio.h>

//不加ws2_32.lib的话就需要动态的加载
#pragma comment(lib, "ws2_32.lib")

#define SERVER_ADDRESS "127.0.0.1"
#define PORT  5150
#define MSGSIZE 1024
#define CPORT 7001

int _tmain(int argc, _TCHAR* argv[])
{
	//Initialize Window socket library
	WSADATA wsaData;
	WSAStartup(0x0202, &wsaData);

	//Create Socket;
	SOCKET sClient;
	sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	//Connect to Server
	SOCKADDR_IN server;
	memset(&server, 0, sizeof(SOCKADDR_IN));
	server.sin_addr.S_un.S_addr = inet_addr(SERVER_ADDRESS);
	server.sin_family = AF_INET;
	server.sin_port = htons(PORT);

	int ret = connect(sClient, (sockaddr*)&server, sizeof(SOCKADDR_IN));
	if(ret == SOCKET_ERROR)
	{
		printf("connet error = %d \n", WSAGetLastError());
		goto exit;
	}

	//send message
	char szMessage[MSGSIZE];
	while(true)
	{
		printf("Send:");
		gets(szMessage);

		if(0 == strcmp("exit" , szMessage))
		{
			goto exit;
		}
		//send message
		send(sClient, szMessage, sizeof(szMessage), 0);
		memset(szMessage, 0, sizeof(szMessage));

		//receive message
		ret = recv(sClient, szMessage, MSGSIZE, 0);
		szMessage[ret] = '\0';
		printf("REceived [%d bytes]: '%s'\n ", ret, szMessage);
	}
exit:
	closesocket(sClient);
	WSACleanup();
	return 0;
}


服务器端代码

 

// server_CompletionPort.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <WinSock2.h>

#pragma comment(lib, "ws2_32.lib")
#define PORT 5150
#define MSGSIZE 1024

typedef enum
{
	RECV_POSTED
}OPERATION_TYPE;

typedef struct
{
	WSAOVERLAPPED overlap;
	WSABUF Buffer;
	char szMessage[MSGSIZE];
	DWORD NumberOfBytesRecvd;
	DWORD Flags;
	OPERATION_TYPE OperationType;
}PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;

DWORD WINAPI WorkerThread(LPVOID CompletionPortID)
{
	HANDLE  CompletionPort  = (HANDLE)CompletionPortID;
	DWORD dwBytesTransferred;
	SOCKET sClient;
	LPPER_IO_OPERATION_DATA lpPerIOData = NULL;

	while(true)
	{
		//this method to check whether the completionPort queue exist request,
		//if exist, it will run the following code, if not exist, it will waiting
		GetQueuedCompletionStatus(
				CompletionPort,
				&dwBytesTransferred,
				(unsigned long*)&sClient,
				(LPOVERLAPPED*)&lpPerIOData,
				INFINITE
			);

		if(dwBytesTransferred == 0xFFFFFFFF)
		{
			return 0;
		}

		if(lpPerIOData->OperationType == RECV_POSTED)
		{
			if(dwBytesTransferred == 0)
			{
				//connection was closed by client
				closesocket(sClient);
				HeapFree(GetProcessHeap(), 0, lpPerIOData);
			}
			else
			{
				lpPerIOData->szMessage[dwBytesTransferred] = '\0';
				send(sClient, lpPerIOData->szMessage, dwBytesTransferred, 0);

				//launch another asynchronous operation for sClient
				///*********************************************************
				memset(lpPerIOData, 0 , sizeof(PER_IO_OPERATION_DATA));
				lpPerIOData->Buffer.len = MSGSIZE;
				lpPerIOData->Buffer.buf = lpPerIOData->szMessage;
				lpPerIOData->OperationType = RECV_POSTED;
				WSARecv(
					sClient,
					&lpPerIOData->Buffer,
					1,
					&lpPerIOData->NumberOfBytesRecvd,
					&lpPerIOData->Flags,
					&lpPerIOData->overlap,
					NULL
					);
				///*********************************************************
			}
		}
	}
}
int _tmain(int argc, _TCHAR* argv[])
{
	//1. Initialize Windows Socket library
	WSADATA wsaData;
	WSAStartup(0x0202, &wsaData);

	//*2. Create Completion port, save its handle, and this handle will useful
	HANDLE CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);

	//*3. Create Worker Thread
	//3.1 the thread number is same as the Processor number
	//3.2 this thread is use to commnute with the client
	SYSTEM_INFO systeminfo;
	GetSystemInfo(&systeminfo);
	DWORD dwThreadId;
	for(int i=0 ; i < systeminfo.dwNumberOfProcessors; i++)
	{
		CreateThread(NULL, 0, WorkerThread, CompletionPort, 0, &dwThreadId);
	}

	SOCKET sListen, sClient= NULL;
	//4. Create listening socket
	sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	//5. Bind
	SOCKADDR_IN local, client;
	local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	local.sin_family = AF_INET;
	local.sin_port = htons(PORT);
	bind(sListen, (sockaddr*)&local, sizeof(SOCKADDR_IN));
	printf("Binded\n");
	//6. Listen
	listen(sListen, 3);
	printf("Listened\n");

	LPPER_IO_OPERATION_DATA lpPerIOData = NULL;
	int nLen = sizeof(sockaddr);
	while(true)
	{
		printf("Accepting...\n");
		//7. accept a connection
		sClient = accept(sListen, (sockaddr*)&client, &nLen);
		
		printf("Accepted client:%s : %d, &%d \n", 
			inet_ntoa(client.sin_addr), ntohs(client.sin_port),WSAGetLastError());
		//*8. Associate the newly arrived client socket with completion port
		//8.1 Whenever the client connect to server, use this method again, 
		//    but this time its function is to bind with the new Socket with the completionPort
		//8.2 After this method create, the preparetion is completed. following with send or recv it.
		CreateIoCompletionPort((HANDLE)sClient, CompletionPort, (DWORD)sClient, 0);
		
		//Launch an asynchronous operation for new arrived connetion
		///*********************************************************
		lpPerIOData = (LPPER_IO_OPERATION_DATA)HeapAlloc(
				GetProcessHeap(),
				HEAP_ZERO_MEMORY,
				sizeof(PER_IO_OPERATION_DATA)
			);
		lpPerIOData->Buffer.len = MSGSIZE;
		lpPerIOData->Buffer.buf = lpPerIOData->szMessage;
		lpPerIOData->OperationType = RECV_POSTED;

		WSARecv(
			sClient,
			&lpPerIOData->Buffer,
			1,
			&lpPerIOData->NumberOfBytesRecvd,
			&lpPerIOData->Flags,
			&lpPerIOData->overlap,
			NULL
			);
		///*********************************************************
	}

	PostQueuedCompletionStatus(CompletionPort, 0xFFFFFFFF, 0, NULL);
	CloseHandle(CompletionPort);
	closesocket(sListen);
	WSACleanup();
	return 0;
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值