加入多播组的所有端点都应该接收发送到该组的数据吗?

发布于 2024-11-28 16:09:19 字数 6022 浏览 2 评论 0原文

如果两个端点连接到两个端口上的 100 个多播组,现在如果我将数据发送到一个组地址和端口 Comb(g1,p1),它是否也不会被其他套接字接收,因为它们也是团体。

如果没有为什么不呢?如果是,那么以下代码有什么问题?

#include "stdafx.h"
#include <stdio.h>
#include <winsock2.h>

void socketCreation(void)
{
  unsigned int i=0;
  u_int    yes=1;

  for(i=0;i<gConfiguration.numSockets;i++)  //200
  {
    if ((gConfiguration.sockArray[i] = WSASocket(AF_INET,SOCK_DGRAM,IPPROTO_UDP,NULL,0,0))== INVALID_SOCKET)
    {
      printf("\n\t Socket Creation failed with error ::%d::", WSAGetLastError());
      WSACleanup();
      exit(1);
    }
    // Allow Multiple Sockets to use the same PORT number */
    if (setsockopt(gConfiguration.sockArray[i],SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes)) < 0) 
    {
      printf("\n\t SetSockOpt for SO_REUSEADDR failed with error ::%d::", WSAGetLastError());
      WSACleanup();
      exit(1);
    }
  }

}

void socketBinding(void)
{
  struct     sockaddr_in addr;
  unsigned int i=0;
  unsigned int j=0;
  unsigned int tempPort =0;
  long localaddr  = inet_addr("127.0.0.1");
  int k = 0;
  for(i = 0;i<gConfiguration.numPorts;i++)
    {
      addr.sin_port=htons(gConfiguration.ports[i]);
      addr.sin_family=AF_INET;
      addr.sin_addr.s_addr=htonl(INADDR_ANY);
      // bind to receive address
      if (bind(gConfiguration.sockArray[i],(struct sockaddr *) &addr,sizeof(addr)) == SOCKET_ERROR) 
      {
        printf("\n\t Bind failed with error ::%d::", WSAGetLastError());
        exit(1);
      }
      printf("\n socket %d bind to port %d\t\n", gConfiguration.sockArray[i], gConfiguration.ports[i]);
      k++;
    }  
}
void joinMCastGroup(void)
{
  struct     ip_mreq mreq = {0};
  unsigned int i=0;
  unsigned int j=0;

  mreq.imr_interface.s_addr=htonl(INADDR_ANY);
  for(i=0;i<gConfiguration.numSockets;i++)
  {
    //In order to be a member of multiple MGroups run a loop
    for(j=0;j<gConfiguration.numAddress;j++)
    {
      //Select MulticastGroup
      mreq.imr_multiaddr.s_addr=gConfiguration.address[j];

      if (setsockopt(gConfiguration.sockArray[i],IPPROTO_IP,IP_ADD_MEMBERSHIP,(char*)&mreq,sizeof(mreq)) < 0) 
      {
        printf("\n\t Setsocketopt IP_ADD_MEMBERSHIP failed with::%d:: on ::%d:: socket",  WSAGetLastError(),j);
        exit(1);
      }
      //printf("\n %d socket is a member of the group add = %d,\n", i, gConfiguration.address[j]);
    }
  }
}

void dataRecv(void)
{
  int        retVal=-1;
  int        nBytes=-1;
  int        addrLen=0;
  char      buffer[MSG_BUF_SIZE];
  struct      sockaddr_in addr;
  fd_set      readFD;
  unsigned int  i=0;
  unsigned int    tickCount =0;

  gLastTickCount=GetTickCount();
  long lTotalPkt = 0;
  timeval timeout;
  timeout.tv_sec = 10;
  timeout.tv_usec = 100000;
  DWORD dwWaitResult = 0;
//  system("cls");
  printf("\n *********************************************** ");
  printf("\n Waiting for packets to come...");
  printf("\n ***********************************************\n ");
  addrLen=sizeof(addr);

  printf("\n Total Seq no to recv = %d\n", gTotalPkt);
  gSeqNo2 = 0;
  dwWaitResult = WaitForSingleObject(mutex, INFINITE);
  if(dwWaitResult == WAIT_OBJECT_0)
  {
    while(1)
    {
      FD_ZERO(&readFD);
      for(i=0;i<gConfiguration.numSockets;i++)
        FD_SET(gConfiguration.sockArray[i],&readFD);

      retVal=select(FD_SETSIZE,&readFD,NULL,NULL,&timeout);

      if(0<retVal)
      {
        for(i=0;i<gConfiguration.numSockets;i++)
        {
          if(FD_ISSET(gConfiguration.sockArray[i],&readFD))
          {
            addrLen=sizeof(addr);
            if ((nBytes=recvfrom(gConfiguration.sockArray[i],buffer,sizeof(buffer),0,(struct sockaddr *) &addr,&addrLen)) < 0) 
            {
              printf("\n\t RecvFrom Error with::%d::\n", WSAGetLastError());
              exit(1);
            }
            //printf("\n recvd on socket no = %d, data=%s, address = %d\n", i, buffer, gConfiguration.address[i]);
            gSeqNo2++;
            gBytesCount++;//= nBytes;
            gTotalByteReceived += gBytesCount;
          }
        }
        //tickCount = GetTickCount();
        //if((tickCount - gLastTickCount) > 1000) //Checking if it's more than 2 seconds or not
        //{

      }
      else
      {
        printf("timeout\n");
      }
      if(gTotalPkt == gSeqNo2)
      {
        printf("\n %d packets recvd.\n", gSeqNo2);
        ReleaseMutex(mutex);
        break;
      }

    }
  }
  ReleaseMutex(mutex);

  printf("\n Total packet Received= %d\n", gSeqNo2);
}
void RecvUsingThread()
{
  int i = 0;
  gtCount = 2;
  gTotalPkt =  gConfiguration.numPacket * gConfiguration.numAddress * gConfiguration.numPorts;//atol(buffer);
  mutex = CreateMutex(NULL, FALSE, NULL);
  if(NULL == mutex)
  {
    printf("\nunable to create mutex.\n.");
  }
  for(i = 0;i<gtCount;i++)
  {
    threadHandle[i] = CreateThread(NULL, 0, ( LPTHREAD_START_ROUTINE )dataRecv, NULL, 0, &threadId[i]);
    if (threadHandle[i] == NULL) 
       {
          printf("Unable to create Thread\n");
       }
  }
  WaitForMultipleObjects(gtCount, threadHandle, TRUE, INFINITE);
  for(i = 0;i<gtCount;i++)
  {
    CloseHandle(threadHandle[i]);
  }

  printf("\nTotal packet recvd = %d\n", gSeqNo2);
}

void socketOperations(void)
{
  int      retVal=-1;
  WSADATA    WsaData;
  // Initialize Winsock version 2.2
  if ((retVal = WSAStartup(MAKEWORD(2,2), &WsaData)) != 0)
  {
    // NOTE: Since Winsock failed to load we cannot use WSAGetLastError 
       // to determine the error code as is normally done when a Winsock 
       // API fails. We have to report the return status of the function.
    printf("\n\t WSAStartup failed with error ::%d::", retVal);
       exit(1);
  }

  //Creating Sockets and setting the SO_REUSEADDR option
  socketCreation();
  //Binding Sockets
  socketBinding();
  //Joining with the Multicast Group.
  joinMCastGroup();
  //Receiving the data on a Socket.
  RecvUsingThread();
}
//100AddrOn2Ports

If two endpoints are joined to say 100 multicast groups on two ports, now if I am sending data to one group address and port comb(g1,p1), should it not get received by other sockets as well because they are also the member of the group.

If no why not? and if yes then what is wrong with following code?

#include "stdafx.h"
#include <stdio.h>
#include <winsock2.h>

void socketCreation(void)
{
  unsigned int i=0;
  u_int    yes=1;

  for(i=0;i<gConfiguration.numSockets;i++)  //200
  {
    if ((gConfiguration.sockArray[i] = WSASocket(AF_INET,SOCK_DGRAM,IPPROTO_UDP,NULL,0,0))== INVALID_SOCKET)
    {
      printf("\n\t Socket Creation failed with error ::%d::", WSAGetLastError());
      WSACleanup();
      exit(1);
    }
    // Allow Multiple Sockets to use the same PORT number */
    if (setsockopt(gConfiguration.sockArray[i],SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes)) < 0) 
    {
      printf("\n\t SetSockOpt for SO_REUSEADDR failed with error ::%d::", WSAGetLastError());
      WSACleanup();
      exit(1);
    }
  }

}

void socketBinding(void)
{
  struct     sockaddr_in addr;
  unsigned int i=0;
  unsigned int j=0;
  unsigned int tempPort =0;
  long localaddr  = inet_addr("127.0.0.1");
  int k = 0;
  for(i = 0;i<gConfiguration.numPorts;i++)
    {
      addr.sin_port=htons(gConfiguration.ports[i]);
      addr.sin_family=AF_INET;
      addr.sin_addr.s_addr=htonl(INADDR_ANY);
      // bind to receive address
      if (bind(gConfiguration.sockArray[i],(struct sockaddr *) &addr,sizeof(addr)) == SOCKET_ERROR) 
      {
        printf("\n\t Bind failed with error ::%d::", WSAGetLastError());
        exit(1);
      }
      printf("\n socket %d bind to port %d\t\n", gConfiguration.sockArray[i], gConfiguration.ports[i]);
      k++;
    }  
}
void joinMCastGroup(void)
{
  struct     ip_mreq mreq = {0};
  unsigned int i=0;
  unsigned int j=0;

  mreq.imr_interface.s_addr=htonl(INADDR_ANY);
  for(i=0;i<gConfiguration.numSockets;i++)
  {
    //In order to be a member of multiple MGroups run a loop
    for(j=0;j<gConfiguration.numAddress;j++)
    {
      //Select MulticastGroup
      mreq.imr_multiaddr.s_addr=gConfiguration.address[j];

      if (setsockopt(gConfiguration.sockArray[i],IPPROTO_IP,IP_ADD_MEMBERSHIP,(char*)&mreq,sizeof(mreq)) < 0) 
      {
        printf("\n\t Setsocketopt IP_ADD_MEMBERSHIP failed with::%d:: on ::%d:: socket",  WSAGetLastError(),j);
        exit(1);
      }
      //printf("\n %d socket is a member of the group add = %d,\n", i, gConfiguration.address[j]);
    }
  }
}

void dataRecv(void)
{
  int        retVal=-1;
  int        nBytes=-1;
  int        addrLen=0;
  char      buffer[MSG_BUF_SIZE];
  struct      sockaddr_in addr;
  fd_set      readFD;
  unsigned int  i=0;
  unsigned int    tickCount =0;

  gLastTickCount=GetTickCount();
  long lTotalPkt = 0;
  timeval timeout;
  timeout.tv_sec = 10;
  timeout.tv_usec = 100000;
  DWORD dwWaitResult = 0;
//  system("cls");
  printf("\n *********************************************** ");
  printf("\n Waiting for packets to come...");
  printf("\n ***********************************************\n ");
  addrLen=sizeof(addr);

  printf("\n Total Seq no to recv = %d\n", gTotalPkt);
  gSeqNo2 = 0;
  dwWaitResult = WaitForSingleObject(mutex, INFINITE);
  if(dwWaitResult == WAIT_OBJECT_0)
  {
    while(1)
    {
      FD_ZERO(&readFD);
      for(i=0;i<gConfiguration.numSockets;i++)
        FD_SET(gConfiguration.sockArray[i],&readFD);

      retVal=select(FD_SETSIZE,&readFD,NULL,NULL,&timeout);

      if(0<retVal)
      {
        for(i=0;i<gConfiguration.numSockets;i++)
        {
          if(FD_ISSET(gConfiguration.sockArray[i],&readFD))
          {
            addrLen=sizeof(addr);
            if ((nBytes=recvfrom(gConfiguration.sockArray[i],buffer,sizeof(buffer),0,(struct sockaddr *) &addr,&addrLen)) < 0) 
            {
              printf("\n\t RecvFrom Error with::%d::\n", WSAGetLastError());
              exit(1);
            }
            //printf("\n recvd on socket no = %d, data=%s, address = %d\n", i, buffer, gConfiguration.address[i]);
            gSeqNo2++;
            gBytesCount++;//= nBytes;
            gTotalByteReceived += gBytesCount;
          }
        }
        //tickCount = GetTickCount();
        //if((tickCount - gLastTickCount) > 1000) //Checking if it's more than 2 seconds or not
        //{

      }
      else
      {
        printf("timeout\n");
      }
      if(gTotalPkt == gSeqNo2)
      {
        printf("\n %d packets recvd.\n", gSeqNo2);
        ReleaseMutex(mutex);
        break;
      }

    }
  }
  ReleaseMutex(mutex);

  printf("\n Total packet Received= %d\n", gSeqNo2);
}
void RecvUsingThread()
{
  int i = 0;
  gtCount = 2;
  gTotalPkt =  gConfiguration.numPacket * gConfiguration.numAddress * gConfiguration.numPorts;//atol(buffer);
  mutex = CreateMutex(NULL, FALSE, NULL);
  if(NULL == mutex)
  {
    printf("\nunable to create mutex.\n.");
  }
  for(i = 0;i<gtCount;i++)
  {
    threadHandle[i] = CreateThread(NULL, 0, ( LPTHREAD_START_ROUTINE )dataRecv, NULL, 0, &threadId[i]);
    if (threadHandle[i] == NULL) 
       {
          printf("Unable to create Thread\n");
       }
  }
  WaitForMultipleObjects(gtCount, threadHandle, TRUE, INFINITE);
  for(i = 0;i<gtCount;i++)
  {
    CloseHandle(threadHandle[i]);
  }

  printf("\nTotal packet recvd = %d\n", gSeqNo2);
}

void socketOperations(void)
{
  int      retVal=-1;
  WSADATA    WsaData;
  // Initialize Winsock version 2.2
  if ((retVal = WSAStartup(MAKEWORD(2,2), &WsaData)) != 0)
  {
    // NOTE: Since Winsock failed to load we cannot use WSAGetLastError 
       // to determine the error code as is normally done when a Winsock 
       // API fails. We have to report the return status of the function.
    printf("\n\t WSAStartup failed with error ::%d::", retVal);
       exit(1);
  }

  //Creating Sockets and setting the SO_REUSEADDR option
  socketCreation();
  //Binding Sockets
  socketBinding();
  //Joining with the Multicast Group.
  joinMCastGroup();
  //Receiving the data on a Socket.
  RecvUsingThread();
}
//100AddrOn2Ports

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

音栖息无 2024-12-05 16:09:19

端口是最终目的地而不是多播组。

因此,发送到端口 100数据包 A 将通过其连接的任何组到达任何已加入的应用程序,除非平台是 Windows,因为 WinSock 提供比 Unix 主机更多的过滤。

您必须使用唯一的多播组和 UDP 端口对,将这一对视为唯一的元组是不够的。

使用 226.0.0.1:500、226.0.0.2:502 等,不要使用226.0.0.1:500、226.0.0.2:500 等。

Ports are the final destination not multicast groups.

Therefore packet A sent to port 100 will reach any joined application it reaches via whatever groups it is connected to unless the platform is Windows because WinSock provides additional filtering than Unix hosts.

You must use unique pairs of multicast group and UDP port it is insufficient to treat the pair as a unique tuple.

Use 226.0.0.1:500, 226.0.0.2:502, etc, do not use 226.0.0.1:500, 226.0.0.2:500, etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文