Client:
//客户端
#include <WINSOCK2.H>
#include <stdio.h>
#include <stdlib.h>
#include <WS2tcpip.h>
//#include "tpipv6.h"
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
#define HELLO_PORT 7905 //定义端口
#define HELLO_GROUP "FF02::99"//"224.0.0.99"//"228.4.5.6" //定义多播目标地址224.0.1.0 - 238.255.255.255
#define BUFFER_SIZE 1024
//客户端需要加入多播组,并实时收取数据包
int main()
{
cout<<"This is Client who join to Some Multicast Group and Receive Data from Multicast Source!"<<endl;
WSADATA wd;
WSAStartup(MAKEWORD(2,2),&wd);
int err=-1;
//SOCKET s;
addrinfo hints;
addrinfo *res = NULL;
memset(&hints,0,sizeof(hints));
//hints.ai_family=PF_UNSPEC;
hints.ai_family=AF_INET6;
hints.ai_socktype=SOCK_DGRAM;
hints.ai_protocol=IPPROTO_UDP;//这里也可以改为0,让系统自己选
hints.ai_flags=AI_NUMERICHOST;
int rc=getaddrinfo((PCSTR)"fe80::6820:ef2d:fece:9fb6","6000",&hints,&res);//解析对方收地址
if(rc!=0)
{
printf("getaddrinfo fail\n");
return 0;
}
SOCKET sockClt=socket(res->ai_family, res->ai_socktype, res->ai_protocol);
/************设置多播相关的选项**************/
int ret ;
const int on = 1; //允许程序的多个实例运行在同一台机器上
ret = setsockopt(sockClt, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
if( ret == SOCKET_ERROR )
{
WSACleanup();
cout<<"Error in setsockopt(SO_REUSEADDR): "<<WSAGetLastError()<<endl;
return 0;
}
//设置多播跳数,实际上应该放在发送端。。
const int routenum = 10;
ret = setsockopt(sockClt,IPPROTO_IPV6,IPV6_MULTICAST_HOPS,\
(char*)&routenum,sizeof(routenum));
if( ret == SOCKET_ERROR )
{
WSACleanup();
cout<<"Error in setsockopt(IP_MULTICAST_TTL): "<<WSAGetLastError()<<endl;
return 0;
}
/************设置多播相关的选项**************/
//char wht[80];
/*绑定socket*/
ret = bind(sockClt, res->ai_addr, res->ai_addrlen);// 绑定端口
//cout<<inet_ntop(AF_INET6,(void *)(res->ai_addr),wht,80)<<endl;
if (SOCKET_ERROR == ret)
{
printf("SOCKET_ERROR\n");
return 0;
}
struct ipv6_mreq mreq6; /*加入广播组*/
inet_pton(AF_INET6,HELLO_GROUP,&mreq6.ipv6mr_multiaddr);
mreq6.ipv6mr_multiaddr.u.Byte;
for (int i=0;i<16;i++)
{
printf("%x",mreq6.ipv6mr_multiaddr.u.Byte[i]);
//cout<<mreq6.ipv6mr_multiaddr.u.Byte[i]<<endl;
}
mreq6.ipv6mr_interface = htonl(INADDR_ANY); /*网络接口为默认*/
/*将本机加入广播组*/
err = setsockopt(sockClt, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,(char *)&mreq6,sizeof(mreq6));
if (err < 0)
{
perror("setsockopt():IPv6_ADD_MEMBERSHIP");
return -4;
}
char buf[BUFFER_SIZE+1]; //读取内容缓冲池
char src[50];
//int ret;//读取内容大小
sockaddr_storage sa;
int iAddrLen=sizeof( sa );//这样只有24位长,不够长度。所以要改为32,实际收到是28:(
ZeroMemory(&sa, sizeof(sa));
while(1)
{
//Sleep(10000);
//clientlen = sizeof(client);
//memset(&client, 0, clientlen);
memset(src,0,sizeof(src));
//cout<<"Can receive?"<<endl;
ret = recvfrom(sockClt, buf, sizeof(buf), 0, (struct sockaddr*)&sa, &iAddrLen );
cout<<ret<<endl;
if ( ret == 0) //do_read在用户直接回车发送了一个空字符串
{
continue;
}
else if( ret == SOCKET_ERROR )
{
if( WSAGetLastError() == WSAEINTR ) //主线程终止recvfrom返回的错
break;
cout<<"Error in recvfrom: "<<WSAGetLastError()<<endl;
//break ;
}
buf[ret] = '\0';
cout<<"Recieve From: "<<inet_ntop(AF_INET6,(void *)&sa,src,50)<<endl;
cout<<"received: "<<buf<<endl;
cout<<"------------------"<<endl;
}
}
Server:
//服务端
#include <WINSOCK2.H>
#include <stdio.h>
#include <WS2tcpip.h>
//#include "tpipv6.h"
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
#define HELLO_PORT 7905 //定义端口
#define HELLO_GROUP "FF02::99"//定义链路范围上的用户多播地址
#define BUFFER_SIZE 1024
int main()
{
cout<<"Ipv6: This is Server for sending data to Multicast Address!"<<endl;
WSADATA wd;
WSAStartup(MAKEWORD(2,2),&wd);
char sendline[BUFFER_SIZE+1];
//SOCKET s;
addrinfo hints;
addrinfo *res = NULL;
memset(&hints,0,sizeof(hints));
//hints.ai_family=PF_UNSPEC;
hints.ai_family=AF_INET6;
hints.ai_socktype=SOCK_DGRAM;
hints.ai_protocol=IPPROTO_UDP;//这里也可以改为0,让系统自己选
hints.ai_flags=AI_NUMERICHOST;
int rc=getaddrinfo((PCSTR)HELLO_GROUP,"6000",&hints,&res);//解析对方收地址
if(rc!=0)
{
printf("getaddrinfo fail\n");
return 0;
}
SOCKET sockClt=socket(res->ai_family, res->ai_socktype, res->ai_protocol);
//char wht[80];
//cout<<res->ai_addr->sa_data[15]<<endl;
//cout<<inet_ntop(AF_INET6,(void *)(res->ai_addr),wht,80)<<endl;
while (1)
{
cin.getline(sendline,BUFFER_SIZE);
if (strncmp(sendline,"end",3)==0)
break;
sendto(sockClt,sendline,strlen(sendline),0,res->ai_addr,res->ai_addrlen);
}
return 0;
}