C++ | 实现UDP广播

简介: 手把手教你实现UDP广播。

包含Socket的头文件:

#include <winsock.h>

想要使用关于Socket的相关类型(SOCKET, SOCKADDR_IN)和函数,需要先引用Socket的头文件。

创建套接字成员变量:

SOCKET m_UdpSocket; //UDP通信套接字        
SOCKADDR_IN m_UdpSocketAddr; //UDP通信套接字地址

Socket通信需要用到SOCKET类型和SOCKADDR_IN类型,所谓Socket,是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。

它是网络环境中进程间通信的API(应用程序编程接口)。通信时其中一个网络应用程序将要传输的一段信息写入它所在主机的Socket中,该Socket通过与网络接口卡(NIC)相连的传输介质将这段信息送到另一台主机的Socket中,使对方能够接收到这段信息。Socket是由IP地址和端口结合的,提供向应用层进程传送数据包的机制。

启动套接字:

WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
    return FALSE;
}

WSAStartup,即WSA(Windows Sockets Asynchronous, Windows异步套接字)的启动命令。

WSAStartup必须是应用程序或DLL调用的第一个Windows Socket函数。它允许应用程序或DLL指明Windows Sockets API的版本号及获得特定Windows Sockets实现的细节。应用程序或DLL只能在一次成功的WSAStartup()调用之后才能调用进一步的Windows Sockets API函数。

创建套接字:

m_UdpSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (m_UdpSocket == INVALID_SOCKET)
{
    WSACleanup();//释放套接字资源
    return FALSE;
}

在任何类型的通信开始之前,都必须先创建出套接字。

  • 创建套接字的参数1为:套接字类型,分为基于文件的套接字(AF_UNIX)和面向网络的套接字(AF_INET);
  • 参数2为:连接方式,分为面向连接的套接字(SOCK_STREAM,指TCP)和面向无连接的套接字(SOCK_DGRAM,指UDP);
  • 参数3为:指定协议,常用的协议有IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_TIPC等,他们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。

我们这里指定的是网络套接字,UDP连接,UDP传输协议。

设置广播权限:

BOOL bBroadcast = TRUE;
setsockopt(m_UdpSocket, SOL_SOCKET, SO_BROADCAST, (const char*)&bBroadcast, sizeof(bBroadcast));
m_UdpSocketAddr.sin_family = AF_INET;
m_UdpSocketAddr.sin_port = htons(atoi(m_strPort.c_str()));

这里调用setsockopt是希望发送UDP数据报的时候,socket发送的数据具有广播特性。

setsockopt的使用还有很多种,可以参考这篇文章:setsockopt用法详解

设置IP为广播地址:

int iPos = 0;
std::vector<std::string> vStringIP = splitString(m_strLocalIP, ".", true);
std::string ipCStr = vStringIP[0] + "." + vStringIP[1] + "." + vStringIP[2] + ".255";//L"255.255.255.255";
m_UdpSocketAddr.sin_addr.S_un.S_addr = inet_addr(ipCStr.c_str()); 
//设置ip为广播地址 /*inet_addr(ip_char);*/ 全网地址:htonl(INADDR_BROADCAST)

逻辑是获取本机的IP地址,然后将IP地址的最后一个数改为255,这个IP地址就是这个网段的广播地址。splitString()函数是我自己写的一个函数,主要用来将IP地址的四个部分存在一个vector中。

启动广播线程:

m_UdpThreadInfo.pThis = this;
m_UdpThreadInfo.isExit = FALSE;
m_UdpThreadInfo.threadHandle = CreateThread(0, 0, ThreadFunction, &m_UdpThreadInfo, 0, 
&(m_UdpThreadInfo.threadID));

我这里是将发送广播数据放在一个线程中实现,在线程中指定一个固定的间隔时间发送数据。

发送广播数据:

if (sendto(m_UdpSocket, data, dataSize, 0, (SOCKADDR*)&m_UdpSocketAddr, 
sizeof(m_UdpSocketAddr)) == SOCKET_ERROR)
{
    return FALSE;
}

调用sendto()函数实现数据的发送。data为发送的数据,类型为char *,dataSize为发送的数据的大小。

停止广播线程,关闭套接字:

m_UdpThreadInfo.isExit = TRUE;
closesocket(m_UdpSocket);//关闭套接字,并等待接收线程结束
WaitForSingleObject(m_UdpThreadInfo.threadHandle, 3000);
CloseHandle(m_UdpThreadInfo.threadHandle);
m_UdpThreadInfo.threadHandle = NULL;

线程函数是一个while()循环,突出线程时,需要将参数isExit置为TRUE。调用closesocket()函数实现关闭套接字。WaitForSingleObject()函数是一种Windows API函数,用来检测线程句柄的信号状态,在某一线程中调用该函数时,线程暂时挂起,如果在指定的挂起时间(ms)内,线程所等待的对象变为信号状态,则函数立即返回,如果到指定时间,句柄所指向的对象还没有编程信号状态,仍然返回。它在这里的作用就是等待线程退出,但是不阻塞主线程。

目录
相关文章
|
网络协议 C++ iOS开发
C++项目实战-UDP服务器
C++项目实战-UDP服务器
125 0
|
网络协议 Linux C语言
linux下CC++网络编程基本:socket实现tcp和udp的例子
linux下CC++网络编程基本:socket实现tcp和udp的例子
244 0
|
2月前
|
网络协议 Linux 网络性能优化
Linux C/C++之TCP / UDP通信
这篇文章详细介绍了Linux下C/C++语言实现TCP和UDP通信的方法,包括网络基础、通信模型、编程示例以及TCP和UDP的优缺点比较。
47 0
Linux C/C++之TCP / UDP通信
|
定位技术 C++
C++实现俄罗斯方块(附代码)
C++实现俄罗斯方块(附代码)
C++实现俄罗斯方块(附代码)
|
机器学习/深度学习 C++
C++实现实现逆时针旋转矩阵
C++实现实现逆时针旋转矩阵
C++实现实现逆时针旋转矩阵
|
编译器 C++ 容器
【C++要笑着学】迭代器适配器 | 内嵌类型实现反向迭代器 | 迭代器萃取
上一章讲解 list 模拟实现时,我们简单的提到了反向迭代器,我们说反向迭代器其实就是对正向迭代器的一种封装 —— 适配器模式(配接器模式)。当时我们做的是简单的了解,本章我们就来探讨这一部分的知识。
160 1
【C++要笑着学】迭代器适配器 | 内嵌类型实现反向迭代器 | 迭代器萃取
|
存储 C++
C++异常处理机制由浅入深, 以及函数调用汇编过程底层刨析. C++11智能指针底层模拟实现
C++异常处理机制由浅入深, 以及函数调用汇编过程底层刨析. C++11智能指针底层模拟实现
C++异常处理机制由浅入深, 以及函数调用汇编过程底层刨析. C++11智能指针底层模拟实现
|
存储 Linux C语言
生产者消费者模式保姆级教程 (阻塞队列解除耦合性) 一文帮你从C语言版本到C++ 版本, 从理论到实现 (一文足以)
生产者消费者模式保姆级教程 (阻塞队列解除耦合性) 一文帮你从C语言版本到C++ 版本, 从理论到实现 (一文足以)
生产者消费者模式保姆级教程 (阻塞队列解除耦合性) 一文帮你从C语言版本到C++ 版本, 从理论到实现 (一文足以)
|
设计模式 安全 定位技术
C++从面试常考实现特殊类到单例模式的实现
C++从面试常考实现特殊类到单例模式的实现
C++从面试常考实现特殊类到单例模式的实现
|
存储 Java 应用服务中间件
线程池设计, 从简单的我们平常设计线程池图解,到生活中的类似线程池的处理现实场景, 到简单的C++模拟nginx写的单链表组织工作队列的简单线程池实现 + nginx 部分源码刨析
线程池设计, 从简单的我们平常设计线程池图解,到生活中的类似线程池的处理现实场景, 到简单的C++模拟nginx写的单链表组织工作队列的简单线程池实现 + nginx 部分源码刨析
线程池设计, 从简单的我们平常设计线程池图解,到生活中的类似线程池的处理现实场景, 到简单的C++模拟nginx写的单链表组织工作队列的简单线程池实现 + nginx 部分源码刨析