winsock 收发广播包 【转】
☛广播包的概念
广播包通常为了如下两个原因使用:1 一个应用程序希望在本地网络中找到一个资源,而应用程序对于该资源的地址又没有任何先验的知识。
2 一些重要的功能,例如路由要求把它们的信息发送给所有找到的邻机。
被广播信息的目的地址取决于这一信息将在何种网络上广播。Internet域中支持一个速记地址用于广播-INADDR_BROADCAST。由于使
用广播以前必须捆绑一个数据报套接口,所以所有收到的广播消息都带有发送者的地址和端口。
广播通信是无连接的通信,通信前不需要建立连接。不需要listen和accept,但需要绑定一个socket用来接收广播。
☛广播包的发送
创建socket
设置socket,例如设置超时、允许广播等
绑定socket。在使用广播前必须绑定一个socket。这一步可有可无,如果没有,系统自动绑定到一个未用端口。
发送广播。广播的端口号要和接收方绑定的端口号一致
#include "stdafx.h"
#include <WinSock2.h>
#include <Windows.h>
#include <string.h>
#pragma comment(lib, "ws2_32.lib")
void autoCleanup()
{
WSACleanup();
}
int _tmain(int argc, _TCHAR* argv[])
{
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested=MAKEWORD(2,2);
int ret;
ret = WSAStartup(wVersionRequested,&wsaData);
int sock = socket(AF_INET, SOCK_DGRAM, 0);
int bc = 1;
//允许发送广播消息
int so_broadcast = TRUE;
ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&so_broadcast, sizeof(so_broadcast));
sockaddr_in addr;
addr.sin_family = AF_INET; //使用互联网际协议,即IP协议
addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addr.sin_port = htons(2526);
//如果仅仅是发送广播,这一步可有可无。没有绑定也能发送广播
//ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
struct sockaddr_in b_addr;
b_addr.sin_family = AF_INET;
b_addr.sin_addr.S_un.S_addr =htonl(INADDR_BROADCAST);
b_addr.sin_port = htons(2527);
char buff[50] = "Hello, world!";
while (1)
{
ret = sendto(sock, buff, strlen(buff), 0, (struct sockaddr*)&b_addr, sizeof(b_addr));
printf("send... %d\n", WSAGetLastError());
Sleep(3000);
}
closesocket(sock);
atexit(autoCleanup);
return 0;
}
☛接收广播包
接收方一定要知道广播方的端口号,然后绑定同样的端口号才能正确接收。道理很简单,如果不绑定到一个端口,它不知道到哪里接收数据。
// send.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <WinSock2.h>
#include <Windows.h>
#include <string.h>
#pragma comment(lib, "ws2_32.lib")
void autoCleanup()
{
WSACleanup();
}
int _tmain(int argc, _TCHAR* argv[])
{
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested=MAKEWORD(2,2);
WSAStartup(wVersionRequested,&wsaData);
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
//这个端口要和广播方广播端口一致
addr.sin_port = htons(2527);
bind(sock, (struct sockaddr *)&addr, sizeof(addr));
struct sockaddr_in from;
int len = sizeof(from);
int ret;
char buff[50];
while (1)
{
ret = recvfrom(sock, buff, 49, 0, (struct sockaddr *)&from, &len);
if (ret > 0)
{
buff[ret] = 0;
printf("%s\n", buff);
printf("%s %d\n", inet_ntoa(from.sin_addr), ntohs(from.sin_port));
}
}
closesocket(sock);
atexit(autoCleanup);
return 0;
}
饮水思源,不忘初心。
要面包,也要有诗和远方。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了