多播报文的发送和接收
来源:互联网 发布:万能进销存软件 编辑:程序博客网 时间:2024/04/28 13:48
1 实验目的
掌握多播的原理及如何进行多播报文的发送和接受
2 注意事项
需包括ws2tcpip.h文件
发送者和所有接受者在同一网内
不考虑TTL值,回环状态
通过setsockopt( )函数设置选项来实现多播数据的发送和接收
3 试验流程
3.1 多播数据发送端流程
l 创建一个数据报套接口
l 设置多播地址(例:239.192.1.2)和端口号(例:12345)
l 调用setsockopt( )函数设置发送的数据报本地接口(IP_MULTICAST_IF)
struct in_addr interface_addr;
setsockopt ( socket, IPPROTO_IP, IP_MULTICAST_IF,
&interface_addr,sizeof(interface_addr) );
l 使用sendto函数发送数据,目标地址为第二步所设置的多播地址
3.2 多播数据接收的流程
l 创建数据报套接口
l 绑定本地地址(INADDR_ANY)和端口号(同发送端)
l 调用setsockopt( )函数设置IP_ADD_MEMBERSHIP选项,加入多播组
struct ip_mreq {
struct in_addr imr_multiaddr; /* IP multicast address of group */
struct in_addr imr_interface; /* local IP address of interface */
};
struct ip_mreq mreq;
setsockopt ( socket, IPPROTO_IP,IP_ADD_MEMBERSHIP,
&mreq, sizeof(mreq));
l 接收数据
4 源代码
4.1 公共代码
#ifndef _MCASTLIB_H_
#define _MCASTLIB_H_
#include <Winsock2.h>
#include <WS2tcpip.h>
#ifdef __cplusplus
extern "C" {
#endif
int mc_join(SOCKET s,in_addr *mcaddr, in_addr *local_if);
int mc_setIF(SOCKET s,const DWORD local_out_if);
int mc_getIF(SOCKET s,DWORD *local_out_if);
int mc_setTTL(SOCKET s,const DWORD ttl);
int mc_getTTL(SOCKET s,DWORD *ttl);
int mc_setLoop(SOCKET s,const BOOL flag);
int mc_getLoop(SOCKET s,BOOL *flag);
int mc_leave(SOCKET s,in_addr *mcaddr, in_addr *local_if);
#ifdef __cplusplus
}
#endif
#endif // _MCASTLIB_H_
#include "MCastlib.h"
int mc_join(SOCKET s,in_addr *mcaddr, in_addr *local_if)
{
ip_mreq mreq;
memcpy(&(mreq.imr_interface), local_if,sizeof(in_addr)); // local if
memcpy(&(mreq.imr_multiaddr), mcaddr, sizeof(in_addr));// multicast group address
return (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP,(char*)&mreq, sizeof(mreq)));
}
//为多播报文设置外出接口
int mc_setIF(SOCKET s,const DWORD local_out_if)
{
return (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,(char*)&local_out_if, sizeof(local_out_if)));
}
// 获取多播报文的外出接口
int mc_getIF(SOCKET s, DWORD *local_out_if)
{
intlen = sizeof(DWORD);
return(getsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, (char*)&local_out_if,&len));
}
// 设置外出多播报文的TTL值,默认为1
int mc_setTTL(SOCKET s, const DWORD ttl)
{
return(setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, (char*)&ttl, sizeof(ttl)));
}
// 获取外出多播报文的ttl值
int mc_getTTL(SOCKET s, DWORD *ttl)
{
intlen = sizeof(DWORD);
return(getsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, (char*)ttl, &len));
}
// 启用或者禁止多播报文环回
int mc_setLoop(SOCKET s, const BOOL flag)
{
return(setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, (char*)&flag, sizeof(flag)));
}
// 获取本地多播回环状态
int mc_getLoop(SOCKET s, BOOL *flag)
{
intlen = sizeof(BOOL);
return(getsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, (char*)flag, &len));
}
// 本地接口local_if离开多播组
int mc_leave(SOCKET s, in_addr *mcaddr,in_addr *local_if)
{
ip_mreqmreq;
memcpy(&(mreq.imr_interface),local_if, sizeof(in_addr)); // local if
memcpy(&(mreq.imr_multiaddr),local_if, sizeof(in_addr)); // multicast group address
return(setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char*)&mreq,sizeof(mreq)));
}
4.2 发送方
// 发送方
#pragma comment(lib, "ws2_32.lib")
#include <stdio.h>
#include <WINSOCK2.H>
#include "MCastlib.h"
void HandleError(char *func);
int main()
{
WSADatawsaData;
WSAStartup(WINSOCK_VERSION,&wsaData);
/*********创建一个数据报套接口****************/
sockaddr_inlocal;
memset(&local,0, sizeof(local));
local.sin_addr.s_addr= htonl(INADDR_ANY);
local.sin_family= AF_INET;
local.sin_port= htons(12345);
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
/*********************************************/
/****调用setsockopt( )函数设置发送的数据报本地接口(IP_MULTICAST_IF)****/
if(mc_setIF(sock, sizeof(sock)) == SOCKET_ERROR)
{
printf("mc_setIF:%d/n", WSAGetLastError());
}
/**********************************************************************/
/* //获取默认的多播报文TTL值和回环状态
DWORDttl;
if(mc_getTTL(sock, &ttl) == SOCKET_ERROR)
{
printf("mc_getTTL:%d/n", WSAGetLastError());
}
BOOLloop;
if(mc_getLoop(sock, &loop) == SOCKET_ERROR)
{
printf("mc_getLoop:%d/n", WSAGetLastError());
}
printf("Multicastdefault: TTL=%d,LoopBack=%d/n", ttl, loop);
//设置TTL值为219
ttl= 219;
if(mc_setTTL(sock, ttl) == SOCKET_ERROR)
{
printf("mc_setTTL:%d/n", WSAGetLastError());
}
*/
/***************设置多播地址和端口号*************/
sockaddr_in to;
memset(&to, 0, sizeof(to));
to.sin_addr.s_addr = inet_addr("239.192.1.2");
to.sin_family = AF_INET;
to.sin_port = htons(12345);
/************************************************/
/***使用sendto函数发送数据,目标地址为第二步所设置的多播地址****/
charbuf[60];
while(true)
{
printf("INPUT:/n");
gets(buf);
buf[strlen(buf)]= '/0';
int res = sendto(sock, buf, strlen(buf) + 1, 0,(sockaddr*)&to, sizeof(to));
if(res == SOCKET_ERROR)
{
HandleError("sendto");
}
else
{
printf("Sendout %d bytes!/n", res);
if(strcmp(buf, "QUIT") == 0)
{
break;
}
}
}
/***************************************************************/
return0;
}
void HandleError(char *func)
{
interrCode = WSAGetLastError();
charinfo[65] = {0};
_snprintf(info,64, "%s: %d/n", func, errCode);
printf(info);
}
4.3 接收方
// 接收方
#pragma comment(lib,"ws2_32.lib")
#include <stdio.h>
#include "MCastlib.h"
int main()
{
//Init the winsock environment
WSADatawsaData;
if(WSAStartup(WINSOCK_VERSION, &wsaData) != 0)
{
printf("Failedto Load a winsock./n");
return0;
}
//创建数据报套接口
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
if(sock == INVALID_SOCKET)
{
printf("socket:%d/n", WSAGetLastError());
return0;
}
//绑定本地地址(INADDR_ANY)和端口号(同发送端)
sockaddr_inlocal;
memset(&local,0, sizeof(local));
local.sin_family= AF_INET;
local.sin_addr.s_addr= htonl(INADDR_ANY);
local.sin_port= htons(12345);
//bind local socket
if (bind(sock, (sockaddr*)&local, sizeof(local)) ==SOCKET_ERROR)
{
printf("bind:%d/n", WSAGetLastError());
return0;
}
//多播组地址
in_addrmcaddr;
mcaddr.S_un.S_addr = inet_addr("239.192.1.2");
//加入多播组
if (mc_join(sock, &mcaddr, &(local.sin_addr)) ==SOCKET_ERROR)
{
printf("JoinMulticast Group: %d/n", WSAGetLastError());
}
//接收数据,考虑此时能收到发往哪些目的地址的UDP报文
charbuf[65];
while(true)
{
memset(buf,0, 65);
if (recvfrom(sock, buf, 64, 0, NULL, NULL) ==SOCKET_ERROR)
{
printf("recvfrom:%d/n", WSAGetLastError());
break;
}
else
{
printf("recvd:%s/n", buf);
if(strcmp(buf, "QUIT") == 0)
{
break;
}
}
}
return0;
}
- 多播报文的发送和接收
- 组播发送和组播接收的源代码例子
- udp多播的发送与接收
- UDP 用户数据报文协议的发送和接收示例
- java UDP报文的发送与接收
- 消费发送接收报文
- 签到发送接收报文
- socket 组播接收和发送实例
- 组播发送和组播接收的源代码例子【转】
- 组播的发送与接收问题
- vb winsock 特殊字符接收和发送报文
- 预授权发送接收报文
- Linux下UDP的组播接收和发送的简单例子
- 通过python下的socket实现组播数据的发送和接收
- 接收http发送的报文,并且打印处理
- 双网卡分别接收和发送组播
- 组播发送接收过程
- 存在多个网络接口时的多播发送与接收问题
- The first step to success.....
- 《BREW进阶与精通——3G移动增值业务的运营、定制与开发》连载之35---BREW应用自动安装
- IT高人的情诗
- 基于1553B总线的ARINC 661指令传输(四)
- 用VERILOG实现门级D触发器和RS触发器
- 多播报文的发送和接收
- HyLab 之煤燃烧
- 今天接到AdToll的Account Manager打来的电话,吓了我一跳
- 反病毒三大国际权威认证介绍
- 传统控件
- ExtJS是什么
- 这几天
- H.264视频编码在VC++.Net中的实现
- 20091222日计划