随笔 - 37  文章 - 0  评论 - 0  阅读 - 62346

Windows多网卡UDP广播问题

最近在项目中遇到一个关于UDP广播的问题,顺藤摸瓜总算找到了原因所在,在此记录一下也分享给遇到相同问题的朋友参考。

(1)项目背景:PC软件需要发送UDP广播包搜索与PC连接的指定设备,然后开启线程循环等待设备回复

(2)现象:PC软件发送UDP广播包后,并没有收到设备的回复

(3)原因排查及定位:

  经过排查跟本地的虚拟网卡有关,将所有虚拟网卡和其他网卡禁用以后就能收到设备的回复了

  通过wireshark进一步抓包发现,在开启虚拟网卡时广播包是通过虚拟网卡发出的,并没有通过与设备连接的那个网卡发送出去,从而导致了广播包有去无回

找到原因那接下来的事情就好办了,但我们肯定不能要求每个用户都手动去禁用自己电脑上的其他网卡,这非常影响用户体验

那么最好的解决方案是:遍历本地的所有网卡,从每个网卡都发送广播包出去,以下为代码实现

复制代码
// 绑定网卡IP发送广播包
bool SendBroadcast(char* ip)
{
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);    // 初始化SOCKET
    
    SOCKET sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    /* 本地端口和地址 */
    SOCKADDR_IN src_addr;
    memset(&src_addr, 0, sizeof(src_addr));
    src_addr.sin_family = AF_INET;    // 指代协议族,在socket编程中只能是AF_INET
    src_addr.sin_port = 0;    // 为0表示由系统自动分配端口
    src_addr.sin_addr.s_addr = inet_addr(ip);

    int ret = bind(sockfd, (SOCKADDR *)&src_addr, sizeof(SOCKADDR));
    if (SOCKET_ERROR == ret) {    // 成功返回0,失败返回-1
        return false;
    }

    bool opt = true;
    ret = setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (char*)&opt, sizeof(opt)); // 设置套接字
    if (SOCKET_ERROR == ret) {    // 成功返回0,失败返回-1
        return false;
    }

    /* 目的端口和地址 */
    SOCKADDR_IN dst_addr;
    memset(&dst_addr, 0, sizeof(dst_addr));
    dst_addr.sin_family = AF_INET;
    dst_addr.sin_port = htons(5555);
    dst_addr.sin_addr.s_addr = INADDR_BROADCAST;    // 广播地址
    
    unsigned int buf[16] = { 0 };
    buf[0] = 0x12345678;
    buf[1] = 0x87654321;

    ret = sendto(sockfd, (char*)buf, 64, 0, (sockaddr*)&dst_addr, sizeof(dst_addr));
    if (SOCKET_ERROR == ret) {    // 成功返回发送的字节数,失败返回-1
        return false;
    }

    return true;
}

int main()
{
    PIP_ADAPTER_INFO pAdapterInfo = NULL;
    ULONG ulSizeAdapterInfo = 0;
    DWORD dwStatus;

    dwStatus = GetAdaptersInfo(pAdapterInfo, &ulSizeAdapterInfo);
    if (dwStatus == ERROR_BUFFER_OVERFLOW) {
        if (!(pAdapterInfo = (PIP_ADAPTER_INFO)malloc(ulSizeAdapterInfo)))
            return;
        dwStatus = GetAdaptersInfo(pAdapterInfo, &ulSizeAdapterInfo);
    }

    if (dwStatus != ERROR_SUCCESS)
        return;

    while (pAdapterInfo)
    {
        PIP_ADDR_STRING ipList = &pAdapterInfo->IpAddressList;
        while (ipList)  // 一个网卡可能有多个IP地址
        {
            SendBroadcast(ipList->IpAddress.String);
            ipList = ipList->Next;
        }
pAdapterInfo
= pAdapterInfo->Next; } return 0; }
复制代码
posted on   Cynthia_W  阅读(2764)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· 单线程的Redis速度为什么快?
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示