• IOCP六:UDP 客户端退出


    实验过程:

            1.线程A在socket s上投递1号WSARecvFrom

            2.Client发送"woyougexiaozhinv,kewoburenshita"

            3.1号WSARecvFrom接收数据,创建线程B

            4.线程B投递2号WSARecvFrom,然后线程A投递3-10号WSARecvFrom

            5.线程B每隔两秒发送"nihaihaoma"

            6.Client接两次后发送"woyougexiaozhinv,kewoburenshita",然后退出


    实验结果:

            1.Client最后发送的数据由2号WSARecvFrom接收

            2.线程B第三次发送数据,显示:发送成功   影响:3号WSARecvFrom以“ret=false, dwNum=0, GetLastError()=1234, 目标地址”返回

               线程B第四次发送数据,显示:发送成功   影响:4号WSARecvFrom以“ret=false, dwNum=0, GetLastError()=1234, 目标地址”返回

               线程B第五次发送数据,显示:发送成功   影响:5号WSARecvFrom以“ret=false, dwNum=0, GetLastError()=1234, 目标地址”返回

               。。。


    实验结论:

            用socket s向一个不存在的地址投递WSASendTo,显示:发送成功,结果:在s上等待接收的WSARecvFrom按投递顺序以”ret=false,dwNum=0,GetLastError()=1234,ppiod->clientAddr=目标地址“四参数返回


    实验结果图:



    实验代码:

    #include <WinSock2.h>
    #include <Windows.h>
    #include <iostream>
    #include <process.h>
    #include <string>
    #include <MSWSock.h>
    #include <set>
    
    #pragma comment(lib, "Ws2_32.lib")
    #pragma comment(lib, "Kernel32.lib")
    #pragma comment(lib, "Mswsock.lib")
    
    #define BUF_LEN 1024
    
    bool flag = true;
    
    enum OperateType
    {
    	OP_RECV,
    	OP_SEND,
    };
    
    typedef struct PER_HANDLE_DATA
    {
    	SOCKET s;
    	SOCKADDR_IN addr;
    }PER_HANDLE_DATA, *LPPER_HANDLE_DATA;
    
    typedef struct PER_IO_DATA
    {
    	OVERLAPPED overlapped;
    	int no;
    	char buf[BUF_LEN]; 
    	int operationType;
    	sockaddr clientAddr;
    }PER_IO_DATA, *LPPER_IO_DATA;
    
    typedef struct Arg
    {
    	SOCKET s;
    	sockaddr addr;
    }Arg;
    
    SOCKET SocketInitBind()
    {
    	SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
    	if(INVALID_SOCKET == s)
    	{
    		std::cout<<"create socket failed : "<<GetLastError()<<std::endl;
    		return INVALID_SOCKET;
    	}
    
    	SOCKADDR_IN	addr;
    	addr.sin_family = AF_INET;
    	addr.sin_addr.S_un.S_addr = INADDR_ANY;
    	addr.sin_port = htons(4444);
    
    	int ret = bind(s, (sockaddr*)&addr, sizeof(addr));
    	if(SOCKET_ERROR == ret)
    	{
    		std::cout<<"bind failed : "<<GetLastError()<<std::endl;
    		return SOCKET_ERROR;
    	}
    
    	return s;
    }
    
    bool PostSendTo(SOCKET s, const sockaddr *clientAddr, const char *buf, int len)
    {
    	LPPER_IO_DATA ppiod = new PER_IO_DATA;
    	ZeroMemory(&(ppiod->overlapped), sizeof(OVERLAPPED));
    	ppiod->operationType = OP_SEND;
    	ppiod->clientAddr = *clientAddr;
    	ppiod->no = 128;
    	memset(ppiod->buf, 0, BUF_LEN);
    	memcpy(ppiod->buf, buf, len);
    
    	WSABUF databuf;
    	databuf.buf = ppiod->buf;
    	databuf.len = len;
    
    	DWORD dwRecv = 0;
    	DWORD dwFlags = 0;
    	int ret = WSASendTo(s, &databuf, 1, &dwRecv, dwFlags, clientAddr, sizeof(sockaddr), &ppiod->overlapped, NULL);
    	if(SOCKET_ERROR == ret && WSA_IO_PENDING != GetLastError())
    	{
    		delete ppiod;
    		return false;
    	}
    
    	return true;
    }
    
    bool PostRecvFrom(SOCKET s, int n)
    {
    	LPPER_IO_DATA ppiod = new PER_IO_DATA;
    
    	//ZeroMemory(&(ppiod->overlapped), sizeof(OVERLAPPED));
    	ZeroMemory(ppiod, sizeof(PER_IO_DATA));
    	ppiod->operationType = OP_RECV;
    	ppiod->no = n;
    	memset(ppiod->buf, 0, BUF_LEN);
    
    	WSABUF databuf;
    	databuf.buf = ppiod->buf;
    	databuf.len = BUF_LEN;
    
    	DWORD dwRecv = 0;
    	DWORD dwFlags = 0;
    	int len = sizeof(sockaddr);
    	int ret = WSARecvFrom(s, &databuf, 1, &dwRecv, &dwFlags, &ppiod->clientAddr, &len, &ppiod->overlapped, NULL);
    	if(SOCKET_ERROR == ret && WSA_IO_PENDING != GetLastError())
    	{
    		delete ppiod;
    		return false;
    	}
    
    	return true;
    }
    
    unsigned int __stdcall Func(void *param)
    {
    	Arg *arg = (Arg*)param;
    	SOCKET s = arg->s;
    	sockaddr addr = arg->addr;
    
    	PostRecvFrom(s, 2);
    
    	while(1)
    	{
    		Sleep(2000);
    		std::string str = "nihaihaoma";
    		PostSendTo(s, &addr, str.c_str(), str.length());
    	}
    
    	_endthreadex(0);
    	return 0;
    }
    
    unsigned int __stdcall ThreadFunc(void *arg)
    {
    	HANDLE hcp = (HANDLE)arg;
    	if(NULL == hcp)
    	{
    		std::cout<<"thread arg error"<<std::endl;
    		return -1;
    	}
    
    	DWORD dwNum = 0;
    	LPPER_HANDLE_DATA pphd;
    	LPPER_IO_DATA ppiod;
    	while(true)
    	{
    		bool ret = GetQueuedCompletionStatus(hcp, &dwNum, (LPDWORD)&pphd, (LPOVERLAPPED*)&ppiod, WSA_INFINITE);
    
    		//线程退出控制,没有释放申请的堆空间,还不完善
    		if(-1 == dwNum)
    		{
    			std::cout<<"Thread Exit"<<std::endl;
    			_endthreadex(0);
    			return 0;
    		}
    
    		//错误发生
    		if(false == ret || 0 == dwNum)
    		{
    			std::cout<<"An Error Occurs : "<<GetLastError()<<" no:"<<ppiod->no<<std::endl;
    			std::cout<<"ret="<<ret<<" dwNum="<<dwNum<<std::endl;
    
    			sockaddr_in sin;
    			memcpy(&sin, &ppiod->clientAddr, sizeof(sin));
    			std::cout<<"---->To:"<<inet_ntoa(sin.sin_addr)<<" Port:"<<sin.sin_port<<std::endl;
    
    			delete(ppiod);
    			continue;
    		}
    
    		int type = ppiod->operationType;
    		if(OP_RECV == type)
    		{
    			//
    			std::cout<<"接收完成"<<std::endl;
    			//
    			sockaddr_in sin;
    			memcpy(&sin, &ppiod->clientAddr, sizeof(sin));
    			char *ip = inet_ntoa(sin.sin_addr);
    			int port = sin.sin_port;
    			std::cout<<"From:"<<ip<<" Port:"<<port<<std::endl;
    			ppiod->buf[dwNum] = '';
    			std::cout<<"Receiver : "<<ppiod->no<<"  "<<ppiod->buf<<std::endl;
    
    			//只允许进入一次
    			if(flag)
    			{
    				flag = false;
    
    				Arg arg;
    				arg.s = pphd->s;
    				arg.addr = ppiod->clientAddr;
    				//测试在s等待接收时,另一线程在s上投递发送会怎样
    				_beginthreadex(NULL, 0, Func, (void*)&arg, 0, NULL);
    				//等待子线程成功读取参数
    				Sleep(500);
    
    				//投递3-10号接收请求
    				for(int i = 3; i < 11; i++)
    				{
    					bool ret = PostRecvFrom(pphd->s, i);
    					if(false == ret)
    					{
    						std::cout<<"PostAccept Failed"<<std::endl;
    						return -1;
    					}
    				}
    			}
    
    			delete ppiod;
    
    			/*ZeroMemory(&(ppiod->overlapped), sizeof(OVERLAPPED));
    			ZeroMemory(ppiod->buf, BUF_LEN);
    			ppiod->no = 14;
    			WSABUF databuf;
    			databuf.buf = ppiod->buf;
    			databuf.len = BUF_LEN;
    
    			DWORD dwRecv = 0;
    			DWORD dwFlags = 0;
    			int len = sizeof(sockaddr);
    			WSARecvFrom(pphd->s, &databuf, 1, &dwRecv, &dwFlags, &ppiod->clientAddr, &len, &ppiod->overlapped, NULL);*/
    		}
    		else if(OP_SEND == type)
    		{
    			//
    			std::cout<<"发送完成"<<std::endl;
    			//
    			sockaddr_in sin;
    			memcpy(&sin, &ppiod->clientAddr, sizeof(sin));
    			std::cout<<"To:"<<inet_ntoa(sin.sin_addr)<<" Port:"<<sin.sin_port<<std::endl;
    
    			delete ppiod;
    		}
    	}
    
    	return 0;
    }
    
    int main()
    {
    	WSADATA ws;
    	if(WSAStartup(MAKEWORD(2, 2), &ws) != 0)
    	{
    		std::cout<<"WSAStartup error : "<<GetLastError()<<std::endl;
    		return -1;
    	}
    
    	HANDLE hcp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
    	if(NULL == hcp)
    	{
    		std::cout<<"create completion port failed : "<<GetLastError()<<std::endl;
    		return -1;
    	}
    
    	std::set<HANDLE> setWorkers;
    	SYSTEM_INFO si;
    	GetSystemInfo(&si);
    	for(int i = 0; i < si.dwNumberOfProcessors * 2 + 2; i++)
    	{
    		HANDLE worker = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc, (LPVOID)hcp, 0, NULL);
    		if(NULL == worker)
    		{
    			std::cout<<"create thread failed : "<<GetLastError()<<std::endl;
    			return -1;
    		}
    		setWorkers.insert(worker);
    	}
    
    	SOCKET s = SocketInitBind();
    	if(INVALID_SOCKET == s)
    	{
    		std::cout<<"socket init failed"<<std::endl;
    		return -1;
    	}
    
    	LPPER_HANDLE_DATA pphd = new PER_HANDLE_DATA;
    	pphd->s = s;
    	CreateIoCompletionPort((HANDLE)s, hcp, (DWORD)pphd, 0);
    
    	//投递编号1接收请求
    	bool ret = PostRecvFrom(s, 1);
    	if(false == ret)
    	{
    		std::cout<<"PostAccept Failed"<<std::endl;
    		return -1;
    	}
    
    	//退出控制
    	/*std::cin.get();
    	for(int i = 0; i < setWorkers.size(); i++)
    		PostQueuedCompletionStatus(hcp, -1, NULL, NULL);*/
    
    	auto iter = setWorkers.begin();
    	for(; iter != setWorkers.end(); iter++)
    		WaitForSingleObject(*iter, INFINITE);
    
    	WSACleanup();
    
    	std::cin.get();
    	return 0;
    }
    


    客户端代码:

    #include <stdio.h> 
    #include <Winsock2.h> 
    #include <iostream>
    
    #pragma comment(lib, "Ws2_32.lib")
    
    int main() 
    { 
    	WSADATA ws;
    
    	if(WSAStartup(MAKEWORD(2, 2), &ws) != 0)
    		return -1;
    
    	sockaddr_in addr; 
    	int len = sizeof(addr); 
    	addr.sin_family = AF_INET; 
    	addr.sin_port = htons(4444);
    	addr.sin_addr.s_addr = inet_addr("192.168.15.14"); 
    	SOCKET s = socket(AF_INET, SOCK_DGRAM, 0); 
    	
    	std::string str = "woyougexiaozhinv,kewoburenshita";
    	int ret = sendto(s, str.c_str(), str.length(), 0, (sockaddr*)&addr, len);
    	if (SOCKET_ERROR == ret) 
    	{
    		std::cout<<"Data Send Fail"<<std::endl;
    		return -1;
    	} 
    
    	char buf[100] = {0};
    	ret = recvfrom(s, buf, 100, 0, (sockaddr*)&addr, &len);
    	if(SOCKET_ERROR == ret)
    	{
    		std::cout<<"Data Recv Fail"<<std::endl;
    		return -1;
    	}
    	std::cout<<buf<<std::endl;
    
    	{
    		char buf[100] = {0};
    		ret = recvfrom(s, buf, 100, 0, (sockaddr*)&addr, &len);
    		if(SOCKET_ERROR == ret)
    		{
    			std::cout<<"Data Recv Fail"<<std::endl;
    			return -1;
    		}
    		std::cout<<buf<<std::endl;
    
    		std::string str = "woyougexiaozhinv,kewoburenshita";
    		int ret = sendto(s, str.c_str(), str.length(), 0, (sockaddr*)&addr, len);
    		if (SOCKET_ERROR == ret) 
    		{
    			std::cout<<"Data Send Fail"<<std::endl;
    			return -1;
    		} 
    	}
    
    	closesocket(s);
    	WSACleanup();   
    	return 0;
    }
    



  • 相关阅读:
    AndroidStudio build.gradle 报错
    点九图片的显示内容区域应作何理解
    【Android Studio快捷键】之导入相应包声明(import packages)
    ListView之EmptyView
    Activity 设置切换动画
    android 中 系统日期时间的获取
    解决Activity启动黑屏及设置android:windowIsTranslucent不兼容activity切换动画问题
    android选择图片或拍照图片上传到服务器(包括上传参数)
    Spring 4 官方文档学习(十)数据访问之OXM
    Spring 4 官方文档学习(十)数据访问之ORM
  • 原文地址:https://www.cnblogs.com/chaikefusibushiji/p/7475630.html
Copyright © 2020-2023  润新知