加入多播组的所有端点都应该接收发送到该组的数据吗?
如果两个端点连接到两个端口上的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
端口是最终目的地而不是多播组。
因此,发送到端口 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.