UDP IOCP 客户端

// iocp.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

//---------------------------------------------------------------------------

//#pragma hdrstop
#include <winsock2.h>
#include <stdio.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
//---------------------------------------------------------------------------

#pragma argsused



SOCKET sockClient;
struct sockaddr_in addrServer;
char buf[32];
int n = 0;
int Init();
char abc[]="lijianmin";
DWORD WINAPI WorkerThread(LPVOID CompletionPortID);
//ljm
typedef enum  
{
   RECV_POSTED,
   SEND_POSTED

}OPERATION_TYPE;       //枚举,表示状态
typedef struct
{
WSAOVERLAPPED   overlap;
WSABUF          Buffer;
char            szMessage[1024];
DWORD           NumberOfBytesRecvd;
DWORD           Flags;
struct sockaddr_in	 dest;
char*			temp;
OPERATION_TYPE OperationType;
}PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;    //定义一个结构体保存IO数据
//ljm

int main(int argc, char* argv[])
{
	//ljm
	int send,recv,iocperrnum;
	WSADATA                  wsaData;
	//SOCKET                   sListen, sClient;
	SOCKADDR_IN              local, client;
	DWORD                    i, dwThreadId;
	int                      iaddrSize = sizeof(SOCKADDR_IN);
	HANDLE                   CompletionPort = INVALID_HANDLE_VALUE;
	HANDLE                   CompletionPort2 = INVALID_HANDLE_VALUE;
	SYSTEM_INFO              systeminfo;
	LPPER_IO_OPERATION_DATA lpPerIOData = NULL;
	//ljm

	CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);//ljm
	// 有几个CPU就创建几个工作者线程
	GetSystemInfo(&systeminfo);
	for(i = 0; i < systeminfo.dwNumberOfProcessors; i++)
	{
	   CreateThread(NULL, 0, WorkerThread, CompletionPort, 0, &dwThreadId);
	}

    if(Init() != 0)
        goto theend;

    //sockClient = socket(AF_INET,SOCK_STREAM,0);
	sockClient = socket(AF_INET,SOCK_DGRAM,0);//ljm
    if(sockClient == INVALID_SOCKET)
    {
        cout<<"socket 失败"<<endl;
        WSACleanup();
        goto theend;
    }

	CompletionPort2=CreateIoCompletionPort((HANDLE)sockClient, CompletionPort, ( ULONG_PTR)sockClient, 0);//ljm
	if(CompletionPort2!=CompletionPort)
		cout<<"CreateIoCompletionPort 2nd 失败"<<endl;
    memset(&addrServer,0,sizeof(sockaddr_in));
    addrServer.sin_family = AF_INET;
    addrServer.sin_addr.s_addr = inet_addr("127.0.0.1");
    addrServer.sin_port = htons(9090);
    cout<<"连接服务器..."<<endl;
	/*
label:
    if(connect(sockClient,(const struct sockaddr *)&addrServer,sizeof(sockaddr)) != 0)
    {
        cout<<"connect 失败"<<endl;
       // WSACleanup();
		Sleep(1000);
        goto label;
		//goto theend;//ljm
    }
   cout<<"connect 成功"<<endl;
   */
   // cout<<"开始发送测试包"<<endl;
    memset(buf,0,32);
    while(true)
    {
		/*
        //sprintf(buf,"第%d个包", n);
		sprintf(buf,"%d", n);
        cout<<"发送:"<<buf<<endl;
        if(send(sockClient,buf,strlen(buf),0) <= 0)
        {
            cout<<"send失败,可能连接断开"<<endl;
            //break;
            goto theend;
        }
        memset(buf,0,32);

        //接收服务端应答
        if(recv(sockClient,buf,256,0) <= 0)
        {
            cout<<"recv失败,可能连接断开"<<endl;
           //break;
           goto theend;
        }
        cout<<"服务器应答:"<<buf<<endl;
        memset(buf,0,32);
*/
	 
		  // 初始化结构体 使用堆内存分配
	   lpPerIOData = (LPPER_IO_OPERATION_DATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PER_IO_OPERATION_DATA));
	   // strcpy(lpPerIOData->szMessage,"lijianmin");
		//memcpy(lpPerIOData->szMessage,&addrServer,sizeof(struct sockaddr_in));
	  // lpPerIOData->Buffer.len = 1024; // len=1024
	  // lpPerIOData->NumberOfBytesRecvd=(DWORD)10;
	   //lpPerIOData->Buffer.buf = lpPerIOData->szMessage;
	   lpPerIOData->OperationType = SEND_POSTED; //操作类型
	   lpPerIOData->dest.sin_addr.S_un.S_addr=addrServer.sin_addr.s_addr;
	   lpPerIOData->dest.sin_family=addrServer.sin_family;
	   lpPerIOData->dest.sin_port=addrServer.sin_port;
	   lpPerIOData->temp=abc;
	   sprintf(buf,"第%d个包", n);
	   strcpy(lpPerIOData->szMessage,buf);
	   lpPerIOData->Buffer.buf=lpPerIOData->szMessage;
	   lpPerIOData->Buffer.len=strlen(lpPerIOData->szMessage);
	  // send=WSASend(sockClient,&lpPerIOData->Buffer,1,&lpPerIOData->NumberOfBytesRecvd,0,&lpPerIOData->overlap,NULL);
        send=WSASendTo(sockClient,&lpPerIOData->Buffer,1,&lpPerIOData->NumberOfBytesRecvd,0,(struct sockaddr*)&addrServer,sizeof(addrServer),&lpPerIOData->overlap,NULL);
	   Sleep(0.04);
	  iocperrnum= WSAGetLastError();
        n++;
    }

    
theend:
    WSACleanup();
    getchar();
    return 0;
}
//---------------------------------------------------------------------------
int Init()
{
    WSAData wsaData;
    if(WSAStartup(MAKEWORD(2,2),&wsaData) != 0)
    {
        cout<<"WSAStartup失败"<<endl;
        return -1;
    }

    if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
    {
        cout<<"SOCKET版本不对"<<endl;
        WSACleanup();
        return -1;
    }
    return 0;
}

//工作者线程有一个参数,是指向完成端口的句柄
DWORD WINAPI WorkerThread(LPVOID CompletionPortID)
{
HANDLE                   CompletionPort=(HANDLE)CompletionPortID;
struct sockaddr_in*  addrto;
DWORD                    dwBytesTransferred;
SOCKET                   sClient;
LPPER_IO_OPERATION_DATA lpPerIOData = NULL;
INT32 addrsize=sizeof(struct sockaddr);
char buf[32];
int rcvnum;
while (TRUE)
{
    printf("enter WorkerThread \n");
   GetQueuedCompletionStatus(    //遇到可以接收数据则返回,否则等待
    CompletionPort,
    &dwBytesTransferred,    //返回的字数
    (PULONG_PTR)&sClient,           //是响应的哪个客户套接字?
    (LPOVERLAPPED *)&lpPerIOData, //得到该套接字保存的IO信息
	INFINITE);       //无限等待咯。不超时的那种。
   if (dwBytesTransferred == 0xFFFFFFFF)
   {
	   printf("dwBytesTransferred == 0xFFFFFFFF\n");
    return 0;
   }
   
   if(lpPerIOData->OperationType == SEND_POSTED) //如果收到数据
   {
    if (dwBytesTransferred == 0)
    {
     //失去客户端连接
		printf("dwBytesTransferred == 0 \n");
     closesocket(sClient);
     HeapFree(GetProcessHeap(), 0, lpPerIOData);        //释放结构体
    }
    else
    {
     //lpPerIOData->szMessage[dwBytesTransferred] = ' ';//收到的数据最后一位是结束标志
		
		sendto(sClient, lpPerIOData->Buffer.buf, lpPerIOData->Buffer.len, 0,(struct sockaddr*)&lpPerIOData->dest,sizeof(struct sockaddr));//将接收到的消息返回
		printf("dest:ip:%d ,port:%d  %s\n",lpPerIOData->dest.sin_addr.S_un.S_addr,lpPerIOData->dest.sin_port,lpPerIOData->Buffer.buf);
		// printf("lpPerIOData->temp:%s \n",lpPerIOData->temp);
		//if(send(sClient, "lijianmin", 9, 0)>0)
     // printf("send ok \n");
		memset(buf,0,32);
        if(rcvnum=recvfrom(sClient, buf, 1024, 0,(struct sockaddr*)&lpPerIOData->dest,&addrsize)>0)
		printf("返回 %s ,recvBYTE:%d",buf,rcvnum);
	
	}

   }
   }
   return 0;
}
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值