免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2103 | 回复: 1
打印 上一主题 下一主题

使用多播IP的几个问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-02-18 14:39 |只看该作者 |倒序浏览
以下是gnu/linux 编程指南中关于多播IP的两个列子,

1.设置过route后运行时
broadcast没问题.
listen端会出现setsockopt(allow multiple socket use): Invalid argument //看书上和man里函数原型,没发现错在哪
listen端只能有一个进程,在开一个时,会出现call to bind: Address already in use后停在那了
在setsockopt中不是设置过SO_REUSEADDR么,以允许一个给定的地址可在同一台计算机上同时被一个以上的进程使用????
/* broadcast.c
* Copyright Mark Watson 1999. Open Source Software License.
*
* Sample broadcast using Multicast IP.
* You must rebuild your Linux kernel to support Multicast IP
* and you have to issue something like this (as root):
*   route add -net 224.0.0.0 netmask 240.0.0.0 dev lo
*/

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

int port = 6789;

void main() {
  int socket_descriptor;
  struct sockaddr_in address;
  // For broadcasting, this socket can be treated like a UDP socket:
  socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0);
  if (socket_descriptor == -1) {
    perror("Opening socket";
    exit(1);
  }
  memset(&address, 0, sizeof(address));
  address.sin_family = AF_INET;
  address.sin_addr.s_addr = inet_addr("224.0.0.1";
  address.sin_port = htons(port);

  while (1) {
    if (sendto(socket_descriptor,
               "test from broadcast Q", sizeof("test from broadcast Q",
               0, (struct sockaddr *)&address, sizeof(address))
        < 0) {
      perror("Trying to broadcast with sendto";
      exit(1);
    }
    sleep(2);
  }
}  


/* listen.c
* Copyright Mark Watson 1999. Open Source Software License.
*
* Sample broadcast using Multicast IP.
* You must rebuild your Linux kernel to support Multicast IP
* and you have to issue something like this (as root):
*   route add -net 224.0.0.0 netmask 240.0.0.0 dev lo
*/

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

char *host_name = "224.0.0.1"; // local host (multicast IP)
int port = 6789;

int  main() {
  struct ip_mreq command;
  u_char loop = 1;  // we want broadcast to also loop back to this computer
  int iter = 0;
  int sin_len;
  char message[256];
  int socket_descriptor;
  struct sockaddr_in sin;
  struct hostent *server_host_name;

  char * str = "A default test string";

   if ((server_host_name = gethostbyname(host_name)) == 0) {
    perror("Error resolving local host\n";
    exit(1);
  }

  bzero(&sin, sizeof(sin));
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = htonl(INADDR_ANY);
  sin.sin_port = htons(port);

  //if ((socket_descriptor = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
  if ((socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
    perror("Error opening socket\n";
    exit(1);
  }

  // allow multiple processes to use this same port???????
  /*
   setsockopt(allow multiple socket use): Invalid argument
   call to bind: Address already in use???????
  */
  loop = 1;
//  u_char share = 1;
  if (setsockopt(socket_descriptor, SOL_SOCKET, SO_REUSEADDR,
                 &loop, sizeof(loop)) < 0) {    ////Invalid argument?????
    perror("setsockopt(allow multiple socket use)";
  }

  if (bind(socket_descriptor, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
    perror("call to bind"; //Address already in use?????
  }

  // allow broadcast to this machine"
  loop = 1;
  if (setsockopt(socket_descriptor, IPPROTO_IP, IP_MULTICAST_LOOP,
                 &loop, sizeof(loop)) < 0) {
    perror("setsockopt(multicast loop on)";
  }

  // join the broadcast group:
  command.imr_multiaddr.s_addr = inet_addr("224.0.0.1";
  command.imr_interface.s_addr = htonl(INADDR_ANY);

  if (command.imr_multiaddr.s_addr == -1) {
    printf("Error: group of 224.0.0.1 not a legal multicast address\n");
  }

  if (setsockopt(socket_descriptor, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                 &command, sizeof(command)) < 0) {
    perror("Error in setsocket(add membership)");
  }

  while (iter++ < 10) {
    sin_len = sizeof(sin);
    if (recvfrom(socket_descriptor, message, 256, 0,
                 (struct sockaddr *)&sin, &sin_len) == -1) {
      perror("Error in receiving response from server\n");
    }

    printf("\nResponse from server:\n\n%s\n", message);
    sleep(2);
  }

  // leave the broadcast group ('struct ip_mreq command' is still setup OK):
  if (setsockopt(socket_descriptor, IPPROTO_IP, IP_DROP_MEMBERSHIP,
                 &command, sizeof(command)) < 0) {
    perror("Error in setsocket(drop membership)");
  }

  close(socket_descriptor);

}  

2.这个程序可以同时运行多多次,但只有一个能接收到所有发送的消息,另外的只能发送,不能接收到.

/* nb_broadcast_and_listen.c
* Copyright Mark Watson 1999. Open Source Software License.
*
* Sample broadcast using Multicast IP and non-blocking sockets.
* You must rebuild your Linux kernel to support Multicast IP
* and you have to issue something like this (as root):
*   route add -net 224.0.0.0 netmask 240.0.0.0 dev lo
*
* Note: this example was derived from the multicast IP broadcast
*       example, and is very similar.
*/

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#include <errno.h>

int port = 9876;

char * host_name = "224.0.0.1"; // local host (multicast IP)

int main() {
  // for setting up for broadcast:
  int out_socket_descriptor;
  struct sockaddr_in address;
  // for setting up for listening for broadcasts
  struct ip_mreq command;
  u_char loop = 1;  // we want broadcast to also loop back to this computer
  int i, iter = 0;
  int sin_len;
  char message[256];
  int in_socket_descriptor;
  struct sockaddr_in sin;
  struct hostent *server_host_name;
  struct sockaddr_in gsin;
  int gsin_len;

  long save_file_flags;

  // For broadcasting, this socket can be treated like a UDP socket:
  out_socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0);
  if (out_socket_descriptor == -1) {
    perror("Opening socket");
    exit(1);
  }

  // allow multiple processes to use this same port:
  loop = 1;
  if (setsockopt(out_socket_descriptor, SOL_SOCKET, SO_REUSEADDR,
                 &loop, sizeof(loop)) < 0) {
    perror("setsockopt(allow multiple socket use)");
    printf("errno =%d\n",errno);
  }
  memset(&address, 0, sizeof(address));
  address.sin_family = AF_INET;
  address.sin_addr.s_addr = inet_addr("224.0.0.1");
  address.sin_port = htons(port);

  // Set up for listening:
   if ((server_host_name = gethostbyname(host_name)) == 0) {
    perror("Error resolving local host\n");
    exit(1);
  }

  bzero(&sin, sizeof(sin));
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = htonl(INADDR_ANY);
  sin.sin_port = htons(port);

  //if ((in_socket_descriptor = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
  if ((in_socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
    perror("Error opening socket\n");
    exit(1);
  }

  // allow multiple processes to use this same port:
  loop = 1;
  if (setsockopt(in_socket_descriptor, SOL_SOCKET, SO_REUSEADDR,
                 &loop, sizeof(loop)) < 0) {
    perror("setsockopt(allow multiple socket use:2)");
    printf("errno =%d\n",errno);
  }

  if (bind(in_socket_descriptor, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
    perror("call to bind");
  }

  // allow broadcast to this machine"
  loop = 1;
  if (setsockopt(in_socket_descriptor, IPPROTO_IP, IP_MULTICAST_LOOP,
                 &loop, sizeof(loop)) < 0) {
    perror("setsockopt(multicast loop on)");
  }

  // join the broadcast group:
  command.imr_multiaddr.s_addr = inet_addr("224.0.1.1");
  command.imr_interface.s_addr = htonl(INADDR_ANY);
// command.imr_interface.s_addr = htonl("127.0.0.1");

  if (command.imr_multiaddr.s_addr == -1) {
    printf("Error: group of 224.0.0.1 not a legal multicast address\n");
  }

  if (setsockopt(in_socket_descriptor, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                 &command, sizeof(command)) < 0) {
    perror("Error in setsocket(add membership)");
  }


  // set socket to non-blocking:
  save_file_flags = fcntl(in_socket_descriptor, F_GETFL);  //get!
  printf("file flags=%ld\n", save_file_flags);
  save_file_flags |= O_NONBLOCK;
  if (fcntl(in_socket_descriptor, F_SETFL, save_file_flags) < 0) { //set!
    perror("trying to set input socket to non-blocking");
  }
  printf("after setting non-blocking,file flags=%ld\n", save_file_flags);

  // main loop that both broadcasts and listens:

  printf("Staring main loop to broadcast and listen...\n");

  while (iter++ < 20) {
    printf("%d iteration\n", iter);
    if ((iter % 7) == 0) { // do a broadcast every 7 times through loop
      printf("sending data...\n");
      if (sendto(out_socket_descriptor,
                 "test from broadcast", sizeof("test from broadcast"),
                 0, (struct sockaddr *)&address, sizeof(address))
          < 0) {
        perror("Trying to broadcast with sendto");
        exit(1);
      }
    }
    sleep(1); // wait a second
    // see if there is any data to read on the non-blocking socket:
    gsin_len = sizeof(gsin);
    i = recvfrom(in_socket_descriptor, message, 256, 0,
                 (struct sockaddr *)&gsin, &gsin_len); //sin???
    if (i > 0) {
      printf("Response from server:%s\n", message);
    } else {
      printf("No data available to read\n");
    }
  }


}

论坛徽章:
0
2 [报告]
发表于 2008-02-19 10:55 |只看该作者
还有哪位能指点下?谢谢
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP