小言_互联网的博客

UDP 组播/多播 C语言实现

871人阅读  评论(0)

目录

逻辑设计:

代码实现

运行结果

224.100.200.1 多播组

224.100.200.52 多播组


思路:

  • PC作为客户机,使用网络调试助手;
  • LS开发板作为服务器端,部署对应程序(代码实现如下);
  • 在UDP基本简单通信的基础上增加两组组播(setsockopt实现,一组也可以),实现组播通信;
  • 运行服务器端程序,打开客户端向组播地址端口发送数据,此时服务器端将收到的数据发回客户端完成一次数据收发。
  • setsockopt 函数介绍见:https://blog.csdn.net/liangren_/article/details/115197754

逻辑设计: 

程序逻辑设计

 

代码实现:


  
  1. #include <stdio.h>
  2. #include <sys/socket.h>
  3. #define __PORT_SERVER 8101 /* 服务器端口号 */
  4. #define GROUP_ADDR_01 "224.100.200.1" /* 组播端口号 1 */
  5. #define GROUP_ADDR_52 "224.100.200.52" /* 组播端口号 2 */
  6. int main (int argc, char **argv)
  7. {
  8. int iRet = -1; /* 操作结果返回值 */
  9. int sockFd = -1; /* socket 描述符 */
  10. struct sockaddr_in sockaddrinRemote; /* 远端地址 */
  11. struct sockaddr_in sockaddrinLocal;
  12. struct ip_mreq mreq;
  13. socklen_t uiAddrLen = sizeof(struct sockaddr_in);
  14. char cRecvBuff[ 257] ={ 0};
  15. register ssize_t sstRecv = 0; /* 接收到的数据长度 */
  16. /*
  17. * 创建 socket 连接
  18. */
  19. sockFd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  20. if (sockFd < 0) {
  21. fprintf( stderr, "create socket error.\n");
  22. return ( -1);
  23. }
  24. /*
  25. * 增加地址复用
  26. */
  27. iRet = setsockopt(sockFd, SOL_SOCKET, SO_REUSEADDR, &iRet, sizeof(iRet));
  28. if (iRet < 0) {
  29. fprintf( stderr, "setsockopt SO_REUSEADDR error.\n");
  30. return ( -1);
  31. }
  32. /*
  33. * 初始化本地地址信息
  34. */
  35. memset(&sockaddrinLocal, 0, sizeof(sockaddrinRemote)); /* 清空地址信息 */
  36. sockaddrinLocal.sin_len = sizeof(struct sockaddr_in); /* 地址结构大小 */
  37. sockaddrinLocal.sin_family = AF_INET; /* 地址族 */
  38. sockaddrinLocal.sin_port = htons(__PORT_SERVER); /* 绑定服务器端口 */
  39. sockaddrinLocal.sin_addr.s_addr = INADDR_ANY;
  40. /*
  41. * 绑定本地地址与端口
  42. */
  43. iRet = bind(sockFd, (struct sockaddr *)&sockaddrinLocal, sizeof(sockaddrinLocal));
  44. if (iRet < 0) { /* 绑定操作失败 */
  45. close(sockFd); /* 关闭已经创建的 socket */
  46. fprintf( stderr, "TCP echo server bind error.\n");
  47. return ( -1); /* 错误返回 */
  48. }
  49. /*
  50. * 多播结构体初始化
  51. */
  52. mreq.imr_multiaddr.s_addr = inet_addr(GROUP_ADDR_01); /* 多播组的IP地址 */
  53. mreq.imr_interface.s_addr = htonl(INADDR_ANY); /* 加入的客服端主机IP地址 */
  54. if (setsockopt(sockFd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) {
  55. perror( "setsockopt");
  56. exit( -1);
  57. }
  58. mreq.imr_multiaddr.s_addr = inet_addr(GROUP_ADDR_52); /* 多播组的IP地址 */
  59. if (setsockopt(sockFd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) {
  60. perror( "setsockopt");
  61. exit( -1);
  62. }
  63. while( 1)
  64. {
  65. memset(cRecvBuff, 0, sizeof(cRecvBuff));
  66. /*
  67. * 从远端接收数据
  68. */
  69. sstRecv = recvfrom(sockFd, ( void *)&cRecvBuff[ 0], 257, 0, (struct sockaddr *)&sockaddrinRemote,&uiAddrLen);
  70. if (sstRecv <= 0) { /* 接收数据失败 */
  71. if ((errno != ETIMEDOUT ) && (errno != EWOULDBLOCK)) { /* 非超时与非阻塞 */
  72. close(sockFd); /* 关闭已经创建的 socket */
  73. fprintf( stderr, "UDP echo server recvfrom error.\n");
  74. return ( -1);
  75. }
  76. continue;
  77. }
  78. sendto(sockFd, ( const void *)&cRecvBuff[ 0], sstRecv, 0, ( const struct sockaddr *)&sockaddrinRemote, uiAddrLen);
  79. }
  80. /*
  81. * 多播关闭
  82. */
  83. setsockopt(sockFd, IPPROTO_IP, IP_DROP_MEMBERSHIP,&mreq, sizeof(mreq));
  84. return ( 0);
  85. }

运行结果:

224.100.200.1 多播组:

224.100.200.1 多播组

 

224.100.200.52 多播组:

224.100.200.52 多播组

 

 


转载:https://blog.csdn.net/Liangren_/article/details/116029676
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场