MFC环境下UDP广播实现(含发送端&接收端)

1 篇文章 0 订阅

PS:自己对经过的坑做个总结,也许对其他读者也有用。总之各种坑emmm,有啥问题欢迎留言指教。必回!
还有,你问已经写好的可以直接用的文件?tan90°不存在的,就一丁点代码,自己写一下印象更深(滑稽)

一、UDP广播简介

UDP广播是不建立稳定的连接情况下 ,通过在指定网段,调用指定的端口,向该网段内所有开放此接口的设备推送消息。对于接收端来说,通过开放对应端口来进行数据的接收工作。
UDP广播存在以下的特点:一对一、一对多、不稳定、速度快等特点

本文适用范围

项目通过验证,后述的接收端和发送端需满足以下条件,其他环境的尚未验证(欢迎大家验证共同探讨)。

  1. 一对一建立UDP广播内容;
  2. 接收端与发送端位于同一个路由器网段之下,IP地址为自动获取状态;
  3. 编译环境为MFC/C++;

二、发送端部分代码

1、头文件

#include <afxsock.h>
#include <afxpriv.h>
#include <winsock2.h>  
#include <windows.h>  
#include <stdio.h>  
#include <string>
#include <vector>

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

2、代码实现

//根据输入的CString内容推送到本地路由器所在的网段
void SendUDPSockeMessage(CString opt)
{
#if TRUE
	//CString转string
	std::string sz2 = CT2A(opt.GetBuffer());
	//string转char*
	const char* szSendToServer = sz2.c_str();
	
    char szBuff[50] = { 0 };  
    WSADATA data;  
    WORD wVersionRequested = MAKEWORD(2, 0);  
    WSAStartup(wVersionRequested, &data);  
  
  	//创建一个UDP的Socket,SOCK_DGRAM代表是UDP
    SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);  
    sockaddr_in addr;  
    addr.sin_family = AF_INET;  
    
    //创建一个端口,这个端口一般要大一点,接收端也要开放同样端口
    addr.sin_port = htons(86563);  
	
	//获取本地路由器IP端
	CString strIPAddr;
	std::vector<CString> string_list;
	{
		//ip获取
		char    HostName[100];
		gethostname(HostName, sizeof(HostName));// 获得本机主机名.
		hostent* hn;
		hn = gethostbyname(HostName);//根据本机主机名得到本机ip
		strIPAddr=inet_ntoa(*(struct in_addr *)hn->h_addr_list[0]);//把ip换成字符串形式
		
		int iPos=0;
		CString strTmp;
		strTmp=strIPAddr.Tokenize(_T("."),iPos);
		while(strTmp.Trim() != _T(""))
		{
			string_list.push_back(strTmp);
			strTmp = strIPAddr.Tokenize(_T("."),iPos);
		}
		int string_list_count = string_list.size();

	}
	//重要:必须在本地路由的255位广播,组成为XXX.XXX.XXX.255
	CString ipCStr=string_list[0]+_T(".")+string_list[1]+_T(".")+string_list[2]+_T(".255");
	char* ip_char = CT2A(ipCStr.GetBuffer(0));
	addr.sin_addr.S_un.S_addr = inet_addr(ip_char); 
	
	//到这里准备就绪
    printf("Client is setup and now trying to connect server...\n");  
  
    sockaddr_in addrServer;  
    int nSockAddrSize = sizeof(addrServer);  
	//重要:必须使用sendto
	//重要:对于char* 需要用strlen获取长度;如果是char [] = {...},这要用sizeof()
    sendto(s, szSendToServer, strlen(szSendToServer), 0, (sockaddr*)&addr, nSockAddrSize);  
    
	//如果有返回信息可以使用这个方法来获取,内容存在szBuff中
    /*recvfrom(s, szBuff, sizeof(szBuff), 0, (sockaddr*)&addrServer, &nSockAddrSize);  
    printf("%s\n", szBuff);  */
  
    closesocket(s);  
    WSACleanup();  
  
    if (getchar()) return ;  
    return ; 

#else
	
#endif
}

3、注意事项

1、发送端在设置广播网段的时候,需要获取到本地的路由器网段,切莫使用系统自带的几个宏:INADDR_ANY、INADDR_LOOPBACK、INADDR_BROADCAST。这几个宏在路由器网段广播时无法收到消息。
2、获取到本地路由后,需要在本地路由的255位广播,组成为XXX.XXX.XXX.255
3、必须使用sendto
4、对于char 需要用strlen获取长度;如果是char [] = {…},这要用sizeof()*
5、recvfrom方法是一个堵塞线程的方式,使用的时候要注意

三、接收端

1、头文件

#include "stdafx.h"
#include <winsock2.h>  
#include <windows.h>  
#include <stdio.h>  

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

2、源代码

int _tmain(int argc, _TCHAR* argv[])
{
	//反馈内容
	static const char szAnswerClient[] = "Hello! You've been connected!";  
    char szBuff[50] = { 0 };  
  
    WSADATA data;  
    WORD wVersionRequired = MAKEWORD(2, 0);  
    WSAStartup(wVersionRequired, &data);  
  
    //创建一个广播的Socket
    SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);  
    sockaddr_in addr;  
    addr.sin_family = AF_INET;  
    //添加同样的端口
    addr.sin_port = htons(86563);  
    //监听任何的地址推送过来的广播
    addr.sin_addr.S_un.S_addr = INADDR_ANY;  
    //绑定端口
    bind(s, (sockaddr*)&addr, sizeof(addr));  
  
  	//准备接收
    printf("Server is setup and now waiting for clients' request...\n");  
  
    sockaddr_in addrClient;  
    int nSockAddrSize = sizeof(addrClient);  
    //收到消息后发送内容
    if (recvfrom(s, szBuff, sizeof(szBuff), 0, (sockaddr*)&addrClient, &nSockAddrSize) > 0) {  
        printf("There is one client(%s) connected!\n", inet_ntoa(addrClient.sin_addr));  
        printf("%s\n", szBuff);  
        //发送
        sendto(s, szAnswerClient, sizeof(szAnswerClient), 0, (sockaddr*)&addrClient, nSockAddrSize);  
    }  
  
    closesocket(s);  
    WSACleanup();  
  
    if (getchar()) return 0;  
    return 0;  
}

3、注意事项

1、接收端在设置监听广播网段的时候,可以使用系统自带的几个宏:INADDR_ANY(任何网段)、INADDR_LOOPBACK(本地网段)、INADDR_BROADCAST(与INADDR_ANY一致)。
2、对于char 需要用strlen获取长度;如果是char [] = {…},这要用sizeof()*
3、recvfrom方法是一个堵塞线程的方式,使用的时候要注意

四、小结

UDP的内容到此就完成了,代码经过测试可以使用。这里的接收端是控制台程序,先开启接收端再开启发送端发送就可以了。设置不同的strlen或者发送字节长度可以发送指定长度的内容
PS:保证同一个网段的方式很简单:两台笔记本,设置为自动IP,然后链接同一个wifi即可。

  • 4
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值