Linux网络编程 之 UDP 组播实例

 

一个很简单udp 组播通信的例子,分别为服务器端和客户端的代码。

 

1、服务器端代码 (multi_udp_server.c)

 

 
  1. #include <sys/types.h>

  2. #include <sys/socket.h>

  3. #include <arpa/inet.h>

  4. #include <stdio.h>

  5. #include <stdlib.h>

  6. #include <string.h>

  7. #include <netdb.h>

  8. #include <errno.h>

  9.  
  10. #define BUFLEN 255

  11. /*********************************************************************

  12. *filename: mcastserver.c

  13. *purpose: 演示组播编程的基本步骤,组播服务器端,关键在于加入组

  14. *tidied by: zhoulifa([email protected]) 周立发(http://zhoulifa.bokee.com)

  15. Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言

  16. *date time:2007-01-25 13:20:00

  17. *Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途

  18. * 但请遵循GPL

  19. *Thanks to: Google.com

  20. *Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力

  21. * 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!

  22. *********************************************************************/

  23. int main(int argc, char **argv)

  24. {

  25. struct sockaddr_in peeraddr;

  26. struct in_addr ia;

  27. int sockfd;

  28. char recmsg[BUFLEN + 1];

  29. unsigned int socklen, n;

  30. struct hostent *group;

  31. struct ip_mreq mreq;

  32.  
  33. /* 创建 socket 用于UDP通讯 */

  34. sockfd = socket(AF_INET, SOCK_DGRAM, 0);

  35. if (sockfd < 0) {

  36. printf("socket creating err in udptalk\n");

  37. exit(1);

  38. }

  39.  
  40. /* 设置要加入组播的地址 */

  41. bzero(&mreq, sizeof(struct ip_mreq));

  42. if (argv[1]) {

  43. if ((group = gethostbyname(argv[1])) == (struct hostent *) 0) {

  44. perror("gethostbyname");

  45. exit(errno);

  46. }

  47. } else {

  48. printf

  49. ("you should give me a group address, 224.0.0.0-239.255.255.255\n");

  50. exit(errno);

  51. }

  52.  
  53. bcopy((void *) group->h_addr, (void *) &ia, group->h_length);

  54. /* 设置组地址 */

  55. bcopy(&ia, &mreq.imr_multiaddr.s_addr, sizeof(struct in_addr));

  56.  
  57. /* 设置发送组播消息的源主机的地址信息 */

  58. mreq.imr_interface.s_addr = htonl(INADDR_ANY);

  59.  
  60. /* 把本机加入组播地址,即本机网卡作为组播成员,只有加入组才能收到组播消息 */

  61. if (setsockopt

  62. (sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,

  63. sizeof(struct ip_mreq)) == -1) {

  64. perror("setsockopt");

  65. exit(-1);

  66. }

  67.  
  68. socklen = sizeof(struct sockaddr_in);

  69. memset(&peeraddr, 0, socklen);

  70. peeraddr.sin_family = AF_INET;

  71. if (argv[2])

  72. peeraddr.sin_port = htons(atoi(argv[2]));

  73. else

  74. peeraddr.sin_port = htons(7838);

  75. if (argv[1]) {

  76. if (inet_pton(AF_INET, argv[1], &peeraddr.sin_addr) <= 0) {

  77. printf("Wrong dest IP address!\n");

  78. exit(0);

  79. }

  80. } else {

  81. printf("no group address given, 224.0.0.0-239.255.255.255\n");

  82. exit(errno);

  83. }

  84.  
  85. /* 绑定自己的端口和IP信息到socket上 */

  86. if (bind

  87. (sockfd, (struct sockaddr *) &peeraddr,

  88. sizeof(struct sockaddr_in)) == -1) {

  89. printf("Bind error\n");

  90. exit(0);

  91. }

  92.  
  93. /* 循环接收网络上来的组播消息 */

  94. for (;;) {

  95. bzero(recmsg, BUFLEN + 1);

  96. n = recvfrom(sockfd, recmsg, BUFLEN, 0,

  97. (struct sockaddr *) &peeraddr, &socklen);

  98. if (n < 0) {

  99. printf("recvfrom err in udptalk!\n");

  100. exit(4);

  101. } else {

  102. /* 成功接收到数据报 */

  103. recmsg[n] = 0;

  104. printf("peer:%s", recmsg);

  105. }

  106. }

  107. }

 

文件编译:gcc -Wall multi_udp_server.c -o server 

 

运行:./server 230.1.1.1 7838

 

2、客户端代码(multi_udp_clinet.c)

 

 

 
  1. #include <sys/types.h>

  2. #include <sys/socket.h>

  3. #include <arpa/inet.h>

  4. #include <stdio.h>

  5. #include <stdlib.h>

  6. #include <string.h>

  7.  
  8. #define BUFLEN 255

  9. /*********************************************************************

  10. *filename: mcastclient.c

  11. *purpose: 演示组播编程的基本步骤,其实这就是一个基本的UDP客户端程序

  12. *tidied by: zhoulifa([email protected]) 周立发(http://zhoulifa.bokee.com)

  13. Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言

  14. *date time:2007-01-25 13:10:00

  15. *Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途

  16. * 但请遵循GPL

  17. *Thanks to: Google.com

  18. *Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力

  19. * 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!

  20. *********************************************************************/

  21. int main(int argc, char **argv)

  22. {

  23. struct sockaddr_in peeraddr, myaddr;

  24.  
  25. int sockfd;

  26. char recmsg[BUFLEN + 1];

  27. unsigned int socklen;

  28.  
  29. /* 创建 socket 用于UDP通讯 */

  30. sockfd = socket(AF_INET, SOCK_DGRAM, 0);

  31. if (sockfd < 0) {

  32. printf("socket creating error\n");

  33. exit(1);

  34. }

  35. socklen = sizeof(struct sockaddr_in);

  36.  
  37. /* 设置对方的端口和IP信息 */

  38. memset(&peeraddr, 0, socklen);

  39. peeraddr.sin_family = AF_INET;

  40. if (argv[2])

  41. peeraddr.sin_port = htons(atoi(argv[2]));

  42. else

  43. peeraddr.sin_port = htons(7838);

  44. if (argv[1]) {

  45. /* 注意这里设置的对方地址是指组播地址,而不是对方的实际IP地址 */

  46. if (inet_pton(AF_INET, argv[1], &peeraddr.sin_addr) <= 0) {

  47. printf("wrong group address!\n");

  48. exit(0);

  49. }

  50. } else {

  51. printf("no group address!\n");

  52. exit(0);

  53. }

  54.  
  55. /* 设置自己的端口和IP信息 */

  56. memset(&myaddr, 0, socklen);

  57. myaddr.sin_family = AF_INET;

  58. if (argv[4])

  59. myaddr.sin_port = htons(atoi(argv[4]));

  60. else

  61. myaddr.sin_port = htons(23456);

  62.  
  63. if (argv[3]) {

  64. if (inet_pton(AF_INET, argv[3], &myaddr.sin_addr) <= 0) {

  65. printf("self ip address error!\n");

  66. exit(0);

  67. }

  68. } else

  69. myaddr.sin_addr.s_addr = INADDR_ANY;

  70.  
  71. /* 绑定自己的端口和IP信息到socket上 */

  72. if (bind

  73. (sockfd, (struct sockaddr *) &myaddr,

  74. sizeof(struct sockaddr_in)) == -1) {

  75. printf("Bind error\n");

  76. exit(0);

  77. }

  78.  
  79. /* 循环接受用户输入的消息发送组播消息 */

  80. for (;;) {

  81. /* 接受用户输入 */

  82. bzero(recmsg, BUFLEN + 1);

  83. if (fgets(recmsg, BUFLEN, stdin) == (char *) EOF)

  84. exit(0);

  85. /* 发送消息 */

  86. if (sendto

  87. (sockfd, recmsg, strlen(recmsg), 0,

  88. (struct sockaddr *) &peeraddr,

  89. sizeof(struct sockaddr_in)) < 0) {

  90. printf("sendto error!\n");

  91. exit(3);

  92. }

  93. printf("'%s' send ok\n", recmsg);

  94. }

  95. }

编译:gcc -Wall multi_udp_clinet.c -o clinet

 

运行:./clinet 230.1.1.1 7838 192.168.1.121 5500

 

运行结果图如下:

Linux网络编程 之 UDP 组播实例
 

只要在客户端,敲入要发的字符,就可以服务器端看到了。