You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
5.3 KiB
C++
188 lines
5.3 KiB
C++
// MulticastSocket.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "MulticastSocket.h"
|
|
#include "Mmc.h"
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CMulticastSocket
|
|
|
|
CMulticastSocket::CMulticastSocket()
|
|
{
|
|
m_RevData = NULL;
|
|
m_nSendersPort = 0;
|
|
m_nLocalPort = 0;
|
|
bForceNoLoopback = FALSE;
|
|
|
|
if (!AfxSocketInit())
|
|
{
|
|
//MessageBox(NULL,_T("Failed to Initialize Sockets"),"ͼÏñÏÔʾ", MB_OK | MB_ICONSTOP);
|
|
MessageBoxEx(NULL,"Failed to Initialize Sockets","ImageShow",MB_OK|MB_ICONSTOP,MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US));
|
|
}
|
|
}
|
|
|
|
CMulticastSocket::~CMulticastSocket()
|
|
{
|
|
}
|
|
|
|
|
|
// Do not edit the following lines, which are needed by ClassWizard.
|
|
#if 0
|
|
BEGIN_MESSAGE_MAP(CMulticastSocket, CAsyncSocket)
|
|
//{{AFX_MSG_MAP(CMulticastSocket)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
#endif // 0
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CMulticastSocket member functions
|
|
|
|
BOOL CMulticastSocket::CreateReceivingSocket(LPCTSTR strGroupIP, UINT nGroupPort)
|
|
{
|
|
/* Create socket for receiving packets from multicast group */
|
|
if(!Create(nGroupPort, SOCK_DGRAM, FD_READ))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL bMultipleApps = TRUE; /* allow reuse of local port if needed */
|
|
SetSockOpt(SO_REUSEADDR, (void*)&bMultipleApps, sizeof(BOOL), SOL_SOCKET);
|
|
|
|
/* Fill m_saHostGroup_in for sending datagrams */
|
|
memset(&m_saHostGroup, 0, sizeof(m_saHostGroup));
|
|
m_saHostGroup.sin_family = AF_INET;
|
|
m_saHostGroup.sin_addr.s_addr = inet_addr(strGroupIP);
|
|
m_saHostGroup.sin_port = htons((USHORT)nGroupPort);
|
|
|
|
/* Join the multicast group */
|
|
m_mrMReq.imr_multiaddr.s_addr = inet_addr(strGroupIP); /* group addr */
|
|
m_mrMReq.imr_interface.s_addr = htons(INADDR_ANY); /* use default */
|
|
|
|
if(setsockopt(m_hSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char FAR *)&m_mrMReq, sizeof(m_mrMReq)) < 0)
|
|
{
|
|
int nn = WSAGetLastError();
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL bOptVal = 1;
|
|
if (setsockopt(m_hSocket, IPPROTO_UDP, 1, (char*)&bOptVal, sizeof(bOptVal)) <0)
|
|
{
|
|
printf("Set UDP_NOCHECKSUM: TRUE\n");
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CMulticastSocket::CreateSendingSocket(UINT nTTL, BOOL bLoopBack)
|
|
{
|
|
if(!m_SendSocket.Create(0, SOCK_DGRAM, 0)) // Create an unconnected UDP socket
|
|
return FALSE;
|
|
|
|
if(!SetTTL(nTTL)) // Set Time to Live as specified by user
|
|
MessageBoxEx(NULL,"Warning! Error Setting TTL","ImageShow",NULL,MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US));
|
|
|
|
SetLoopBack(bLoopBack); // Enable/Disable Loopback
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CMulticastSocket::SetTTL(UINT nTTL)
|
|
{
|
|
/* Set Time to Live to parameter TTL */
|
|
if(m_SendSocket.SetSockOpt(IP_MULTICAST_TTL, &nTTL, sizeof(int), IPPROTO_IP) == 0)
|
|
return FALSE; /* Error Setting TTL */
|
|
else
|
|
return TRUE; /* else TTL set successfully */
|
|
}
|
|
|
|
void CMulticastSocket::SetLoopBack(BOOL bLoop)
|
|
{
|
|
/* Set LOOPBACK option to TRUE OR FALSE according to IsLoop parameter */
|
|
int nLoopBack = (int)bLoop;
|
|
if(m_SendSocket.SetSockOpt(IP_MULTICAST_LOOP, &nLoopBack, sizeof(int), IPPROTO_IP) == 0)
|
|
{
|
|
if(!bLoop) /* if required to stop loopback */
|
|
{
|
|
bForceNoLoopback = TRUE; /* Internally making a note that loopback has to be disabled forcefilly */
|
|
|
|
// Get IP/Port for send socket in order to disable loopback forcefully */
|
|
char localHost[255];
|
|
gethostname(localHost, 255);
|
|
struct hostent *host = gethostbyname(localHost); /* Get local host IP */
|
|
m_strLocalIP = inet_ntoa (*(struct in_addr*)*host->h_addr_list);
|
|
CString Dummy; // Dummy string to be passed to the GetSockName function
|
|
m_SendSocket.GetSockName(Dummy, m_nLocalPort); /* Get Port Number for Sending Port */
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CMulticastSocket::OnReceive(int nErrorCode)
|
|
{
|
|
int nError = ReceiveFrom (m_strBuffer, 10240, m_strSendersIP, m_nSendersPort);
|
|
|
|
if(nError == SOCKET_ERROR)
|
|
{
|
|
MessageBoxEx(NULL,"Error receiving data from the host group","ImageShow",NULL,MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US));
|
|
}
|
|
else
|
|
{
|
|
if (!bForceNoLoopback || (bForceNoLoopback && !(m_strSendersIP == m_strLocalIP && m_nSendersPort == m_nLocalPort)))
|
|
{
|
|
// 1. If loopbackback is not to be forced then interface handles the loopback itself
|
|
// 2. If you have to loopback and SOCKOPT LOOPBACK fails, no problem, interfaces loopback by default
|
|
// 3. If you have to stop loopback and SOCKOPT LOOPBACK fails, ignore messages coming from your own sending socket
|
|
|
|
if ( m_RevData != NULL)
|
|
{
|
|
m_RevData( m_strBuffer, nError);
|
|
}
|
|
}
|
|
}
|
|
|
|
CAsyncSocket::OnReceive(nErrorCode);
|
|
}
|
|
|
|
BOOL CMulticastSocket::LeaveGroup()
|
|
{
|
|
if(setsockopt (m_hSocket, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char FAR *)&m_mrMReq, sizeof(m_mrMReq)) < 0)
|
|
return FALSE;
|
|
|
|
m_SendSocket.Close(); // Close sending socket
|
|
Close();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CMulticastSocket::SendTo(const void* strMessage, int nSize)
|
|
{
|
|
if(m_SendSocket.SendTo(strMessage, nSize, (SOCKADDR*)&m_saHostGroup, sizeof(SOCKADDR), 0) == SOCKET_ERROR)
|
|
{
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
BOOL CMulticastSocket::JoinGroup(CString GroupIP, UINT nGroupPort, UINT nTTL, BOOL bLoopback)
|
|
{
|
|
if(!CreateReceivingSocket(GroupIP, nGroupPort)) /* Create Socket for receiving and join the host group */
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if(!CreateSendingSocket(nTTL, bLoopback)) /* Create Socket for sending */
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
} |