完成端口通信例子

代码贴上来以后慢慢修改

服务端代码:

  1. #include <WinSock2.h>   
  2.   
  3. #define BUFFER_SIZE 1024   
  4. #define OP_READ    18   
  5. #define OP_WRITE   28   
  6. #define OP_ACCEPT  38   
  7. #define CHECK_CODE 0x010110   
  8.   
  9. BOOL bStopThread = false;  
  10.   
  11. typedef struct _PER_HANDLE_DATA  
  12. {  
  13.     SOCKET s;  
  14.     sockaddr_in addr;      // 客户端地址   
  15.     char buf[BUFFER_SIZE];  
  16.     int nOperationType;  
  17. }PER_HANDLE_DATA, *PPER_HANDLE_DATA;  
  18.   
  19. #pragma pack(1)   
  20. typedef struct MsgAsk  
  21. {  
  22.     int iCode;  
  23.     int iBodySize;  
  24.     char szBuffer[32];  
  25. }MSG_ASK, *PMSG_ASK;  
  26.   
  27. typedef struct MsgBody  
  28. {  
  29.     int iBodySize;  
  30.     int iOpType;  
  31.     char szBuffer[64];  
  32. }MSG_BODY, *PMSG_BODY;  
  33.   
  34. typedef struct MsgAck  
  35. {  
  36.     int  iCheckCode;  
  37.     char szBuffer[32];  
  38. }MSG_ACK, *PMSG_ACK;  
  39. #pragma pack()   
  40.   
  41. DWORD WINAPI ServerThread(LPVOID lpParam)  
  42. {  
  43.     // 得到完成端口句柄   
  44.     HANDLE           hCompletion = (HANDLE)lpParam;  
  45.     DWORD            dwTrans;  
  46.     PPER_HANDLE_DATA pPerHandle;  
  47.     OVERLAPPED*      pOverLapped;  
  48.   
  49.     while (!bStopThread)  
  50.     {  
  51.         // 在关联到此完成端口的所有套接字上等待I/O完成   
  52.         BOOL bOK = ::GetQueuedCompletionStatus(hCompletion,  
  53.             &dwTrans, (PULONG_PTR)&pPerHandle, &pOverLapped, WSA_INFINITE);  
  54.         if (!bOK)  
  55.         {  
  56.             ::closesocket(pPerHandle->s);  
  57.             ::GlobalFree(pPerHandle);  
  58.             ::GlobalFree(pOverLapped);  
  59.             continue;  
  60.         }  
  61.         switch(pPerHandle->nOperationType)  
  62.         {  
  63.         case OP_READ:  
  64.             {  
  65.                 MSG_ASK msgAsk = {0};  
  66.                 memcpy(&msgAsk, pPerHandle->buf, sizeof(msgAsk));  
  67.                 if (msgAsk.iCode != CHECK_CODE  
  68.                     || msgAsk.iBodySize != sizeof(msgAsk))  
  69.                 {  
  70.                     printf("error\n");  
  71.                 }  
  72.                 else  
  73.                 {  
  74.                     msgAsk.szBuffer[strlen(msgAsk.szBuffer) + 1] = '\n';  
  75.                     printf(msgAsk.szBuffer);  
  76.                     printf("Recv bytes = %d, msgAsk.size = %d\n", dwTrans, msgAsk.iBodySize);  
  77.                 }  
  78.   
  79.                 MSG_BODY msgBody = {0};  
  80.                 memcpy(&msgBody, pPerHandle->buf + msgAsk.iBodySize, sizeof(MSG_BODY));  
  81.                 if (msgBody.iOpType == OP_READ && msgBody.iBodySize == sizeof(MSG_BODY))  
  82.                 {  
  83.                     printf("msgBody.szBuffer = %s\n", msgBody.szBuffer);  
  84.                 }  
  85.   
  86.                 MSG_ACK msgAck = {0};  
  87.                 msgAck.iCheckCode = CHECK_CODE;  
  88.                 memcpy(msgAck.szBuffer, "This is the ack package",  
  89.                     strlen("This is the ack package"));  
  90.   
  91.                 // 继续投递发送I/O请求   
  92.                 pPerHandle->nOperationType = OP_WRITE;  
  93.                 WSABUF buf;  
  94.                 buf.buf = (char*)&msgAck;  
  95.                 buf.len = sizeof(MSG_ACK);  
  96.   
  97.                 OVERLAPPED *pol = (OVERLAPPED *)::GlobalAlloc(GPTR, sizeof(OVERLAPPED));  
  98.   
  99.                 DWORD dwFlags = 0, dwSend = 0;  
  100.                 ::WSASend(pPerHandle->s, &buf, 1, &dwSend, dwFlags, pol, NULL);   
  101.             }  
  102.             break;  
  103.         case OP_WRITE:  
  104.             {  
  105.                 if (dwTrans == sizeof(MSG_ACK))  
  106.                 {  
  107.                     printf("Transfer successfully\n");  
  108.                 }  
  109.                 // 然后投递接收I/O请求   
  110.             }  
  111.             break;  
  112.         case OP_ACCEPT:  
  113.             break;  
  114.         }  
  115.     }  
  116.   
  117.     return 0;  
  118. }  
  119.   
  120. DWORD InitWinsock()  
  121. {  
  122.     DWORD dwRet = 0;  
  123.   
  124.     WSADATA wsaData;    
  125.     dwRet = WSAStartup(MAKEWORD(2,2), &wsaData);    
  126.     if (dwRet != NO_ERROR)    
  127.     {    
  128.         printf("error code = %d\n", GetLastError());    
  129.         dwRet = GetLastError();    
  130.     }    
  131.   
  132.     return dwRet;  
  133. }  
  134.   
  135. void UnInitWinsock()  
  136. {  
  137.     WSACleanup();  
  138. }  
  139.   
  140. int main(int argc, _TCHAR* argv[])  
  141. {  
  142.     int nPort = 5000;  
  143.   
  144.     InitWinsock();  
  145.       
  146.     // 创建完成端口对象   
  147.     HANDLE hCompletion = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);  
  148.     if (hCompletion == NULL)  
  149.     {  
  150.         DWORD dwRet = GetLastError();  
  151.         return dwRet;  
  152.     }  
  153.     ::CreateThread(NULL, 0, ServerThread, (LPVOID)hCompletion, 0, 0);  
  154.   
  155.     // 创建监听套接字   
  156.     SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  
  157.     SOCKADDR_IN si;  
  158.     si.sin_family = AF_INET;  
  159.     si.sin_port = ::htons(nPort);  
  160.     si.sin_addr.s_addr = INADDR_ANY;  
  161.     ::bind(sListen, (sockaddr*)&si, sizeof(si));  
  162.     ::listen(sListen, 10);  
  163.   
  164.     while (TRUE)  
  165.     {  
  166.         SOCKADDR_IN saRemote;  
  167.         int nRemoteLen = sizeof(saRemote);  
  168.         printf("Accepting...\n");  
  169.         SOCKET sNew = ::accept(sListen, (sockaddr*)&saRemote, &nRemoteLen);  
  170.         //SOCKET sNew = ::accept(sListen, NULL, NULL);   
  171.         if (sNew == INVALID_SOCKET)  
  172.         {  
  173.             continue;  
  174.         }  
  175.         printf("Accept one!\n");  
  176.   
  177.         // 接受新连接后,创建一个per-handle数据,并关联到完成端口对象   
  178.         PPER_HANDLE_DATA pPerHandle = (PPER_HANDLE_DATA)::GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA));  
  179.         pPerHandle->s = sNew;  
  180.         memcpy(&pPerHandle->addr, &saRemote, nRemoteLen);  
  181.         pPerHandle->nOperationType = OP_READ;  
  182.         ::CreateIoCompletionPort((HANDLE) pPerHandle->s, hCompletion, (ULONG_PTR)pPerHandle, 0);  
  183.   
  184.         // 投递一个接收请求   
  185.         OVERLAPPED *pol = (OVERLAPPED *)::GlobalAlloc(GPTR, sizeof(OVERLAPPED));  
  186.         WSABUF buf;  
  187.         buf.buf = pPerHandle->buf;  
  188.         buf.len = BUFFER_SIZE;  
  189.         DWORD dwRecv = 0;  
  190.         DWORD dwFlags = 0;  
  191.         ::WSARecv(pPerHandle->s, &buf, 1, &dwRecv, &dwFlags, pol, NULL);  
  192.     }  
  193.   
  194.     return 0;  
  195. }  
#include <WinSock2.h>

#define BUFFER_SIZE 1024
#define OP_READ    18
#define OP_WRITE   28
#define OP_ACCEPT  38
#define CHECK_CODE 0x010110

BOOL bStopThread = false;

typedef struct _PER_HANDLE_DATA
{
	SOCKET s;
	sockaddr_in addr;      // 客户端地址
	char buf[BUFFER_SIZE];
	int nOperationType;
}PER_HANDLE_DATA, *PPER_HANDLE_DATA;

#pragma pack(1)
typedef struct MsgAsk
{
	int iCode;
	int iBodySize;
	char szBuffer[32];
}MSG_ASK, *PMSG_ASK;

typedef struct MsgBody
{
	int iBodySize;
	int iOpType;
	char szBuffer[64];
}MSG_BODY, *PMSG_BODY;

typedef struct MsgAck
{
	int  iCheckCode;
	char szBuffer[32];
}MSG_ACK, *PMSG_ACK;
#pragma pack()

DWORD WINAPI ServerThread(LPVOID lpParam)
{
	// 得到完成端口句柄
	HANDLE           hCompletion = (HANDLE)lpParam;
	DWORD            dwTrans;
	PPER_HANDLE_DATA pPerHandle;
	OVERLAPPED*      pOverLapped;

	while (!bStopThread)
	{
		// 在关联到此完成端口的所有套接字上等待I/O完成
		BOOL bOK = ::GetQueuedCompletionStatus(hCompletion,
			&dwTrans, (PULONG_PTR)&pPerHandle, &pOverLapped, WSA_INFINITE);
		if (!bOK)
		{
			::closesocket(pPerHandle->s);
			::GlobalFree(pPerHandle);
			::GlobalFree(pOverLapped);
			continue;
		}
		switch(pPerHandle->nOperationType)
		{
		case OP_READ:
			{
				MSG_ASK msgAsk = {0};
				memcpy(&msgAsk, pPerHandle->buf, sizeof(msgAsk));
				if (msgAsk.iCode != CHECK_CODE
					|| msgAsk.iBodySize != sizeof(msgAsk))
				{
					printf("error\n");
				}
				else
				{
					msgAsk.szBuffer[strlen(msgAsk.szBuffer) + 1] = '\n';
					printf(msgAsk.szBuffer);
					printf("Recv bytes = %d, msgAsk.size = %d\n", dwTrans, msgAsk.iBodySize);
				}

				MSG_BODY msgBody = {0};
				memcpy(&msgBody, pPerHandle->buf + msgAsk.iBodySize, sizeof(MSG_BODY));
				if (msgBody.iOpType == OP_READ && msgBody.iBodySize == sizeof(MSG_BODY))
				{
					printf("msgBody.szBuffer = %s\n", msgBody.szBuffer);
				}

				MSG_ACK msgAck = {0};
				msgAck.iCheckCode = CHECK_CODE;
				memcpy(msgAck.szBuffer, "This is the ack package",
					strlen("This is the ack package"));

				// 继续投递发送I/O请求
				pPerHandle->nOperationType = OP_WRITE;
				WSABUF buf;
				buf.buf = (char*)&msgAck;
				buf.len = sizeof(MSG_ACK);

				OVERLAPPED *pol = (OVERLAPPED *)::GlobalAlloc(GPTR, sizeof(OVERLAPPED));

				DWORD dwFlags = 0, dwSend = 0;
				::WSASend(pPerHandle->s, &buf, 1, &dwSend, dwFlags, pol, NULL); 
			}
			break;
		case OP_WRITE:
			{
				if (dwTrans == sizeof(MSG_ACK))
				{
					printf("Transfer successfully\n");
				}
				// 然后投递接收I/O请求
			}
			break;
		case OP_ACCEPT:
			break;
		}
	}

	return 0;
}

DWORD InitWinsock()
{
	DWORD dwRet = 0;

	WSADATA wsaData;  
	dwRet = WSAStartup(MAKEWORD(2,2), &wsaData);  
	if (dwRet != NO_ERROR)  
	{  
		printf("error code = %d\n", GetLastError());  
		dwRet = GetLastError();  
	}  

	return dwRet;
}

void UnInitWinsock()
{
	WSACleanup();
}

int main(int argc, _TCHAR* argv[])
{
	int nPort = 5000;

	InitWinsock();
	
	// 创建完成端口对象
	HANDLE hCompletion = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
	if (hCompletion == NULL)
	{
		DWORD dwRet = GetLastError();
		return dwRet;
	}
	::CreateThread(NULL, 0, ServerThread, (LPVOID)hCompletion, 0, 0);

	// 创建监听套接字
	SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	SOCKADDR_IN si;
	si.sin_family = AF_INET;
	si.sin_port = ::htons(nPort);
	si.sin_addr.s_addr = INADDR_ANY;
	::bind(sListen, (sockaddr*)&si, sizeof(si));
	::listen(sListen, 10);

	while (TRUE)
	{
		SOCKADDR_IN saRemote;
		int nRemoteLen = sizeof(saRemote);
		printf("Accepting...\n");
		SOCKET sNew = ::accept(sListen, (sockaddr*)&saRemote, &nRemoteLen);
		//SOCKET sNew = ::accept(sListen, NULL, NULL);
		if (sNew == INVALID_SOCKET)
		{
			continue;
		}
		printf("Accept one!\n");

		// 接受新连接后,创建一个per-handle数据,并关联到完成端口对象
		PPER_HANDLE_DATA pPerHandle = (PPER_HANDLE_DATA)::GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA));
		pPerHandle->s = sNew;
		memcpy(&pPerHandle->addr, &saRemote, nRemoteLen);
		pPerHandle->nOperationType = OP_READ;
		::CreateIoCompletionPort((HANDLE) pPerHandle->s, hCompletion, (ULONG_PTR)pPerHandle, 0);

		// 投递一个接收请求
		OVERLAPPED *pol = (OVERLAPPED *)::GlobalAlloc(GPTR, sizeof(OVERLAPPED));
		WSABUF buf;
		buf.buf = pPerHandle->buf;
		buf.len = BUFFER_SIZE;
		DWORD dwRecv = 0;
		DWORD dwFlags = 0;
		::WSARecv(pPerHandle->s, &buf, 1, &dwRecv, &dwFlags, pol, NULL);
	}

	return 0;
}

客户端代码(客户端没用完成端口):

  1. #include <WinSock2.h>   
  2.   
  3. #define CHECK_CODE 0x010110   
  4. #define OP_READ   18   
  5. #define OP_WRITE  28   
  6. #define OP_ACCEPT 38   
  7.   
  8. #pragma pack(1)   
  9.   
  10. typedef struct MsgAsk  
  11. {  
  12.     int iCode;  
  13.     int iBodySize;  
  14.     char szBuffer[32];  
  15. }MSG_ASK, *PMSG_ASK;  
  16.   
  17. typedef struct MsgBody  
  18. {  
  19.     int iBodySize;  
  20.     int iOpType;  
  21.     char szBuffer[64];  
  22. }MSG_BODY, *PMSG_BODY;  
  23.   
  24. typedef struct MsgAck  
  25. {  
  26.     int  iCheckCode;  
  27.     char szBuffer[32];  
  28. }MSG_ACK, *PMSG_ACK;  
  29.   
  30. #pragma pack()   
  31.   
  32. DWORD SendAll(SOCKET &clientSock, char* buffer, int size)  
  33. {  
  34.     DWORD dwStatus = 0;  
  35.     char  *pTemp   = buffer;  
  36.     int   total    = 0, count = 0;  
  37.   
  38.     while(total < size)   
  39.     {  
  40.         count = send(clientSock, pTemp, size - total, 0);  
  41.         if(count < 0)   
  42.         {  
  43.             dwStatus = WSAGetLastError();  
  44.             break;  
  45.         }  
  46.         total += count;  
  47.         pTemp += count;  
  48.     }  
  49.   
  50.     return dwStatus ;  
  51. }  
  52.   
  53. DWORD RecvAll(SOCKET &sock, char* buffer, int size)    
  54. {    
  55.     DWORD dwStatus = 0;    
  56.     char *pTemp    = buffer;    
  57.     int total      = 0, count = 0;    
  58.   
  59.     while (total < size)    
  60.     {    
  61.         count = recv(sock, pTemp, size-total, 0);    
  62.         if (count < 0)    
  63.         {    
  64.             dwStatus = WSAGetLastError();    
  65.             break;    
  66.         }    
  67.   
  68.         total += count;    
  69.         pTemp += count;    
  70.     }    
  71.   
  72.     return dwStatus;    
  73. }    
  74.   
  75. int _tmain(int argc, _TCHAR* argv[])  
  76. {  
  77.     WSADATA wsaData;    
  78.     int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);    
  79.     if (iResult != NO_ERROR)    
  80.     {    
  81.         printf("error code = %d\n", GetLastError());    
  82.         return -1;    
  83.     }    
  84.   
  85.     sockaddr_in clientAddr;    
  86.     clientAddr.sin_addr.s_addr = inet_addr("127.0.0.1");    
  87.     clientAddr.sin_family      = AF_INET;    
  88.     clientAddr.sin_port        = htons(5000);    
  89.   
  90.     SOCKET clientSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);    
  91.     if (clientSock == INVALID_SOCKET)    
  92.     {    
  93.         printf("Create socket failed, error code = %d\n", WSAGetLastError());    
  94.         return -1;    
  95.     }    
  96.   
  97.     //connect     
  98.     while (connect(clientSock, (SOCKADDR *)&clientAddr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)    
  99.     {    
  100.         printf("Connecting...\n");    
  101.         Sleep(1000);    
  102.     }    
  103.   
  104.     MSG_ASK msgAsk = {0};  
  105.     msgAsk.iBodySize = sizeof(MSG_ASK);  
  106.     msgAsk.iCode = CHECK_CODE;  
  107.     memcpy(msgAsk.szBuffer, "This is a header", strlen("This is a header"));  
  108.   
  109.     // 发送头部   
  110.     SendAll(clientSock, (char*)&msgAsk, msgAsk.iBodySize);  
  111.   
  112.     MSG_BODY msgBody = {0};  
  113.     msgBody.iBodySize = sizeof(MSG_BODY);  
  114.     msgBody.iOpType = OP_READ;  
  115.     memcpy(msgBody.szBuffer, "This is the body", strlen("This is the body"));  
  116.   
  117.     // 发送body   
  118.     SendAll(clientSock, (char*)&msgBody, msgBody.iBodySize);  
  119.   
  120.     MSG_ACK msgAck = {0};  
  121.   
  122.     RecvAll(clientSock, (char*)&msgAck, sizeof(msgAck));  
  123.     if (msgAck.iCheckCode == CHECK_CODE)  
  124.     {  
  125.         printf("The process is successful, msgAck.szBuffer = %s \n", msgAck.szBuffer);  
  126.     }  
  127.     else  
  128.     {  
  129.         printf("failed\n");  
  130.     }  
  131.   
  132.     closesocket(clientSock);  
  133.     WSACleanup();  
  134.   
  135.     return 0;  
  136. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值