• devc++ 使用 winsock 实现 UDP 局域网 WIFI 广播


    参考链接

    使用UDP发送广播报_udp广播 inaddr_broadcast-CSDN博客

    UDP接收端收不到广播的消息问题排查_unity upd广播连接不上是什么情况-CSDN博客

     如何禁用自己电脑的虚拟网卡-百度经验 (baidu.com)

    但是wifi 会屏蔽255.255.255.255 广播地址,所以 255.255.255.255 需要借助手机 wifi 路由实现真正局域网内广播,两台电脑连上同一个手机热点后,就可以发消息了。

    一般的局域网游戏需要 UDP 广播,然后获取到 IP 才能定向发送消息。

    而广播 UDP 的方法和 UDP 定向发送的 方法有些出入,这里是 移植到 DEVC++ 的 UDP 局域网广播方法。

    参考第二条连接,在两台电脑连上同一个手机热点后,如果 UDP 还收不到消息:

    同一个交换机下 是可以收到广播的 还有就是
    电脑的虚拟网卡会拦截广播操作,因为你没有指定一个地址,所以代码正确的情况下,发送不出去或者接收不到,只需要考虑以下两种情况。
    1.广播端虚拟网卡没有禁用
    2.接收端虚拟网卡没有禁用

    PS.虚拟网卡一般是装了虚拟机才会有的。

    服务端

    1. // 服务器端
    2. // Server.cpp : Defines the entry point for the console application.
    3. //
    4. #include
    5. #include
    6. #pragma comment(lib, "ws2_32.lib")
    7. #pragma warning(disable : 4996)
    8. const int MAX_BUF_LEN = 255;
    9. int main(int argc, CHAR* argv[])
    10. {
    11. WORD wVersionRequested;
    12. WSADATA wsaData;
    13. int err;
    14. // 启动socket api
    15. wVersionRequested = MAKEWORD( 2, 2 );
    16. err = WSAStartup( wVersionRequested, &wsaData );
    17. if ( err != 0 )
    18. {
    19. return -1;
    20. }
    21. if ( LOBYTE( wsaData.wVersion ) != 2 ||
    22. HIBYTE( wsaData.wVersion ) != 2 )
    23. {
    24. WSACleanup( );
    25. return -1;
    26. }
    27. // 创建socket
    28. SOCKET connect_socket;
    29. connect_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    30. if(INVALID_SOCKET == connect_socket)
    31. {
    32. err = WSAGetLastError();
    33. printf("/""socket/"" error! error code is %d/n", err);
    34. return -1;
    35. }
    36. SOCKADDR_IN sin;
    37. sin.sin_family = AF_INET;
    38. sin.sin_port = htons(3779);
    39. sin.sin_addr.s_addr = INADDR_BROADCAST; // 255.255.255.255 但是会被路由器屏蔽,不过借用手机热点可以广播,只要两个电脑连同一个手机热点就能广播
    40. bool bOpt = true;
    41. //设置该套接字为广播类型
    42. setsockopt(connect_socket, SOL_SOCKET, SO_BROADCAST, (char*)&bOpt, sizeof(bOpt));
    43. int nAddrLen = sizeof(SOCKADDR);
    44. char buff[MAX_BUF_LEN] = "";
    45. int nLoop = 0;
    46. while(1)
    47. {
    48. nLoop++;
    49. sprintf(buff, "%8d", nLoop);
    50. // 发送数据
    51. int nSendSize = sendto(connect_socket, buff, strlen(buff), 0, (SOCKADDR*)&sin, nAddrLen);
    52. if(SOCKET_ERROR == nSendSize)
    53. {
    54. err = WSAGetLastError();
    55. printf("/""sendto/"" error!, error code is %d/n", err);
    56. return -1;
    57. }
    58. printf("Send: %s/n", buff);
    59. Sleep(500);
    60. }
    61. return 0;
    62. }

    客户端

    1. // 客户端
    2. // Client.cpp : Defines the entry point for the console application.
    3. //
    4. #include
    5. #include
    6. #pragma comment(lib, "ws2_32.lib")
    7. #pragma warning(disable : 4996)
    8. const int MAX_BUF_LEN = 255;
    9. int main(int argc, CHAR* argv[])
    10. {
    11. WORD wVersionRequested;
    12. WSADATA wsaData;
    13. int err;
    14. // 启动socket api
    15. wVersionRequested = MAKEWORD( 2, 2 );
    16. err = WSAStartup( wVersionRequested, &wsaData );
    17. if ( err != 0 )
    18. {
    19. return -1;
    20. }
    21. if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 )
    22. {
    23. WSACleanup( );
    24. return -1;
    25. }
    26. // 创建socket
    27. SOCKET connect_socket;
    28. connect_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    29. if(INVALID_SOCKET == connect_socket)
    30. {
    31. err = WSAGetLastError();
    32. printf("/""socket/"" error! error code is %d/n", err);
    33. return -1;
    34. }
    35. // 用来绑定套接字
    36. SOCKADDR_IN sin;
    37. sin.sin_family = AF_INET;
    38. sin.sin_port = htons(3779);
    39. sin.sin_addr.s_addr = 0;
    40. // 用来从网络上的广播地址接收数据
    41. SOCKADDR_IN sin_from;
    42. sin_from.sin_family = AF_INET;
    43. sin_from.sin_port = htons(3779); // 端口和服务端一致
    44. sin_from.sin_addr.s_addr = INADDR_ANY; // 接收全部广播
    45. //设置该套接字为广播类型,
    46. bool bOpt = true;
    47. setsockopt(connect_socket, SOL_SOCKET, SO_BROADCAST, (char*)&bOpt, sizeof(bOpt));
    48. // 绑定套接字
    49. err = bind(connect_socket, (SOCKADDR*)&sin, sizeof(SOCKADDR));
    50. if(SOCKET_ERROR == err)
    51. {
    52. err = WSAGetLastError();
    53. printf("/""bind/"" error! error code is %d/n", err);
    54. return -1;
    55. }
    56. int nAddrLen = sizeof(SOCKADDR);
    57. char buff[MAX_BUF_LEN] = "";
    58. while(1)
    59. {
    60. // 接收数据
    61. int nSendSize = recvfrom(connect_socket, buff, MAX_BUF_LEN, 0, (SOCKADDR*)&sin_from, &nAddrLen);
    62. if(SOCKET_ERROR == nSendSize)
    63. {
    64. err = WSAGetLastError();
    65. printf("/""recvfrom/"" error! error code is %d/n", err);
    66. return -1;
    67. }
    68. buff[nSendSize] = '/0';
    69. printf("Recv: %s/n", buff);
    70. }
    71. return 0;
    72. }

  • 相关阅读:
    http和https的区别
    Dubbo分布式服务框架常见问题解答汇总
    深度学习的初始化(暂时)
    校验 GPT-4 真实性的三个经典问题:快速区分 GPT-3.5 与 GPT-4,并提供免费测试网站
    你是不是足够了解Lambda表达式?
    便携式脑卒中检测仪是不是离现实不远了?
    SpringMVC整合Shiro与filterChainDefinitions过滤器配置
    NSSCTF之Misc篇刷题记录(16)
    【打卡】【Linux的设备驱动管理之内核对象】21天学习挑战赛—RK3399平台开发入门到精通-Day15
    【C++】借助cout进行控制台文本输出的基本原理及复杂格式控制方法
  • 原文地址:https://blog.csdn.net/a1309602336/article/details/136127311