随笔 - 298  文章 - 377  trackbacks - 0
<2007年8月>
2930311234
567891011
12131415161718
19202122232425
2627282930311
2345678

常用链接

留言簿(34)

随笔分类

随笔档案

文章档案

相册

收藏夹

搜索

  •  

最新评论

阅读排行榜

评论排行榜

Multicasting

多播通讯让网络客户充分享受了广播的便捷而又不用再担心网络会被风暴阻塞,所有这一切都归功于 IGMP 协议的实施。
多播地址是一个D类的IP地址(224.0.0.0-239.255.255.255),其中有一些是为特殊用途而分配的,详细分配情况请参考 RFC1700。
这里只讲述IP多播。IP多播是无根多播,下面只罗列简单的程序实现,详细的规范请参考相应的文档。

#define MCASTADDR "234.5.6.7"
#define MCASTPORT 65500
#define COMMBUFSIZE 1024

// 使用Winsock2
if(WSAStartup(MAKEWORD(2,2),&wsd)!=0) return FALSE;
// 创建多播套接字
SOCKET sock=WSASocket(AF_INET,
SOCK_DGRAM,
0,
NULL,
0,
WSA_FLAG_MULTIPOINT_C_LEAF|
WSA_FLAG_MULTIPOINT_D_LEAF|
WSA_FLAG_OVERLAPPED);
// 绑定套接字
SOCKADDR_IN saiLocal;
saiLocal.sin_family=AF_INET;
saiLocal.sin_port=htons(MCASTPORT);
saiLocal.sin_addr.S_un.S_addr=INADDR_ANY;
if(bind(sock,(SOCKADDR*)&saiLocal,sizeof(saiLocal))==SOCKET_ERROR) return FALSE;
// 设置套接字选项
unsigned long ulNoneBlockingIO=1;
if(SOCKET_ERROR==ioctlsocket(sock, FIONBIO,&ulNoneBlockingIO)) return FALSE;
// Set TTL to 8
int nOpt=8;
if(setsockopt(sock,IPPROTO_IP,IP_MULTICAST_TTL,(char*)&nOpt,sizeof(nOpt))==SOCKET_ERROR) return FALSE;
// Set Loopback
if(m_bLoopBack)
{
BOOL bOpt=0;
if(setsockopt(sock,IPPROTO_IP,IP_MULTICAST_LOOP,(char*)&bOpt,sizeof(bOpt))==SOCKET_ERROR) return FALSE;
}
// 加入多播组
m_saiRemote.sin_family=AF_INET;
m_saiRemote.sin_port=htons(MCASTPORT);
m_saiRemote.sin_addr.S_un.S_addr=inet_addr(MCASTADDR);
DWORD dwFlags=(m_bSender)?JL_SENDER_ONLY:JL_RECEIVER_ONLY;
SOCKET sockM=WSAJoinLeaf(sock,(SOCKADDR*)&m_saiRemote,sizeof(m_saiRemote),NULL,NULL,NULL, NULL,dwFlags);
if(sockM==INVALID_SOCKET)
{
closesocket(sock);
WSACleanup();
return FALSE;
}
// 发送
int nRet=sendto(sock,(char*)pBuf,len,0,(SOCKADDR*)&m_saiRemote,sizeof(m_saiRemote));
// 接收
SOCKADDR_IN sai_From;
int len = sizeof(sai_From);
BYTE buf[COMMBUFSIZE]={'\0'};
int nRetRecv=recvfrom(sock,(char*)buf,COMMBUFSIZE,0,(SOCKADDR*)&sai_From,&len);
// 结束

// 附上一个配置函数
#include "Winsock2.h"
#include "Ws2tcpip.h"

#include "iprtrmib.h"
#include "ipexport.h"
#include "iptypes.h"
#include "iphlpapi.h"

#pragma comment(lib,"ws2_32.lib"
#pragma comment(lib,"iphlpapi.lib"

typedef struct tagNIC
{
int nNum; // 多少块网卡
unsigned char szHostName[150]; // 主机名
unsigned char szAddr[7*10]; // 每块网卡地址以 0为间隔255.255.255.255.
unsigned char szMac[7*10]; // 每块网卡MAC地址0为间隔0x000x040x760x3F0x5F0xA9.
}
NICADDR,*LPNICADDR;

typedef struct tagConfigParam
{
BOOL  bSender; // [IN] 是发送还是接收
char* pszMcastAddr; // [IN] 多播组地址
WORD  wMcastPort; // [IN] 多播端口
NICADDR stuAddr; // [OUT]本地网卡地址信息,函数回填
}
CONFIGPARAM,*LPCONFIGPARAM;

void FuncConfig(CONFIGPARAM* pParam)
{
m_bSender=pParam->bSender;
if(pParam->pszMcastAddr!=NULL)
m_dwMulticastGroup=inet_addr(pParam->pszMcastAddr);
if(pParam->wMcastPort!=0)
m_dwPort=pParam->wMcastPort;
memset(&(pParam->stuAddr),0,sizeof(NICADDR));
char name[MAX_PATH]={'\0'};
if(0==gethostname(name,MAX_PATH))
{
if(strlen(name)>0) strcpy((char*)pParam->stuAddr.szHostName,name);
HOSTENT* HostEnt;
HostEnt=gethostbyname(name);
int n=0;
int m=0;
BOOL bNoConnected=TRUE;
if(HostEnt!=NULL)
{
IP_ADAPTER_INFO AdapterInfo[16];
PIP_ADAPTER_INFO pAdapterInfo;
DWORD dwBufLen=sizeof(AdapterInfo);

DWORD dwRet=GetAdaptersInfo(
AdapterInfo,
&dwBufLen);
if(dwRet==ERROR_SUCCESS) pAdapterInfo=AdapterInfo;

for(int i=0;HostEnt->h_addr_list[i]!=NULL;i++)
{
in_addr ia;
memset(&ia,0,sizeof(ia));
ia.S_un.S_addr = *((unsigned long*)HostEnt->h_addr_list[i]);
char* pszIP = inet_ntoa(ia);
int nLen=strlen(pszIP);
memmove(pParam->stuAddr.szAddr+n,pszIP,nLen);
n+=strlen(pszIP);
n++;

if(dwRet==ERROR_SUCCESS)
{
if(pAdapterInfo)
{
memmove(pParam->stuAddr.szMac+m,pAdapterInfo->Address,6);
pAdapterInfo=pAdapterInfo->Next;
m+=7;
}
}

pParam->stuAddr.nNum++;
}
}
}
}
posted on 2007-08-17 13:18 聂文龙 阅读(364) 评论(0)  编辑 收藏 引用 所属分类: net work

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理