写了两个简单的控制台程序:Sender和Receiver,用于发送接收组播消息。
代码如下:
------------------------------------Sender.c
#include "stdafx.h"
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#define MCASTADDR "224.0.1.0" //本例使用的多播组地址。
#define MCASTPORT 6701 //本地端口号。
#define BUFSIZE 1024 //发送数据缓冲大小。
#pragma comment(lib, "Ws2_32.lib")
int main(int argc, char* argv[])
{
struct sockaddr_in remote;
SOCKET sock,sockM;
TCHAR sendbuf[BUFSIZE];
int len = sizeof( struct sockaddr_in);
// 初始化WinSock2.2
WSADATA wsd;
if( WSAStartup( MAKEWORD(2,2),&wsd) != 0 )
{
printf("WSAStartup() failed\n");
return -1;
}
if((sock=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,WSA_FLAG_MULTIPOINT_C_LEAF|WSA_FLAG_MULTIPOINT_D_LEAF|
WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("socket failed with:%d\n",WSAGetLastError());
WSACleanup();
return -1;
}
// 加入多播组
remote.sin_family = AF_INET;
remote.sin_port = htons(MCASTPORT);
remote.sin_addr.s_addr = inet_addr( MCASTADDR );
if(( sockM = WSAJoinLeaf(sock,(SOCKADDR*)&remote,sizeof(remote),NULL,NULL,NULL,NULL,
JL_BOTH)) == INVALID_SOCKET)
{
printf("WSAJoinLeaf() failed:%d\n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return -1;
}
// 发送多播数据,当用户在控制台输入"QUIT"时退出。
while(1)
{
printf("SEND : ");
scanf("%s",sendbuf);
if( sendto(sockM,(char*)sendbuf,strlen(sendbuf),0,(struct
sockaddr*)&remote,sizeof(remote))==SOCKET_ERROR)
{
printf("sendto failed with: %d\n",WSAGetLastError());
closesocket(sockM);
closesocket(sock);
WSACleanup();
return -1;
}
if(strcmp(sendbuf,"QUIT")==0 || strcmp(sendbuf, "quit")==0)
break;
Sleep(500);
}
closesocket(sockM);
closesocket(sock);
WSACleanup();
return 0;
}
-----------------------------------------Receiver.c
#include "stdafx.h"
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#define MCASTADDR "224.0.1.0" //本例使用的多播组地址。
#define MCASTPORT 6701 //绑定的本地端口号。
#define BUFSIZE 1024 //接收数据缓冲大小。
#pragma comment(lib, "Ws2_32.lib")
int main(int argc, char* argv[])
{
struct sockaddr_in local;
struct sockaddr_in remote;
struct sockaddr_in from;
SOCKET sock,sockM;
TCHAR recvbuf[BUFSIZE];
/*struct ip_mreq mcast; // Winsock1.0 */
int len = sizeof(struct sockaddr_in);
int ret;
//初始化WinSock2.2
WSADATA wsd;
if( WSAStartup( MAKEWORD(2,2),&wsd) != 0 )
{
printf("WSAStartup() failed\n");
return -1;
}
/*创建一个SOCK_DGRAM类型的SOCKET
其中,WSA_FLAG_MULTIPOINT_C_LEAF表示IP多播在控制面层上属于"无根"类型;
WSA_FLAG_MULTIPOINT_D_LEAF表示IP多播在数据面层上属于"无根",有关控制面层和
数据面层有关概念请参阅MSDN说明。*/
if((sock=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,
WSA_FLAG_MULTIPOINT_C_LEAF|WSA_FLAG_MULTIPOINT_D_LEAF|WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("socket failed with:%d\n",WSAGetLastError());
WSACleanup();
return -1;
}
//将sock绑定到本机某端口上。
local.sin_family = AF_INET;
local.sin_port = htons(MCASTPORT);
local.sin_addr.s_addr = htonl(INADDR_ANY);
if( bind(sock,(struct sockaddr*)&local,sizeof(local)) == SOCKET_ERROR )
{
printf( "bind failed with:%d \n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return -1;
}
//加入多播组
remote.sin_family = AF_INET;
remote.sin_port = htons(MCASTPORT);
remote.sin_addr.s_addr = inet_addr( MCASTADDR );
/* Winsock1.0 */
/*
mcast.imr_multiaddr.s_addr = inet_addr(MCASTADDR);
mcast.imr_interface.s_addr = INADDR_ANY;
if(
setsockopt(sockM,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char*)&mcast,sizeof(mcast))
== SOCKET_ERROR)
{
printf("setsockopt(IP_ADD_MEMBERSHIP) failed:%d\n",WSAGetLastError());
closesocket(sockM);
WSACleanup();
return -1;
}
*/
/* Winsock2.0*/
if(( sockM = WSAJoinLeaf(sock,(SOCKADDR*)&remote,sizeof(remote),NULL,NULL,NULL,NULL,JL_BOTH)) == INVALID_SOCKET)
{
printf("WSAJoinLeaf() failed:%d\n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return -1;
}
//接收多播数据,当接收到的数据为"QUIT"时退出。
while(1)
{
if(( ret = recvfrom(sock,recvbuf,BUFSIZE,0,(struct sockaddr*)&from,&len)) == SOCKET_ERROR)
{
printf("recvfrom failed with:%d\n",WSAGetLastError());
closesocket(sockM);
closesocket(sock);
WSACleanup();
return -1;
}
if( strcmp(recvbuf,"QUIT") == 0 )
break;
else
{
recvbuf[ret] = '\0';
printf("RECV:' %s ' FROM <%s> \n",recvbuf,inet_ntoa(from.sin_addr));
}
}
closesocket(sockM);
closesocket(sock);
WSACleanup();
return 0;
}
请问一下使用预留多播地址为224.0.1.0~238.255.255.255,可用于全球范围(如Internet)或网络协议 为什么不能在英特网上组播呢?请知道的高手指教
代码如下:
------------------------------------Sender.c
#include "stdafx.h"
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#define MCASTADDR "224.0.1.0" //本例使用的多播组地址。
#define MCASTPORT 6701 //本地端口号。
#define BUFSIZE 1024 //发送数据缓冲大小。
#pragma comment(lib, "Ws2_32.lib")
int main(int argc, char* argv[])
{
struct sockaddr_in remote;
SOCKET sock,sockM;
TCHAR sendbuf[BUFSIZE];
int len = sizeof( struct sockaddr_in);
// 初始化WinSock2.2
WSADATA wsd;
if( WSAStartup( MAKEWORD(2,2),&wsd) != 0 )
{
printf("WSAStartup() failed\n");
return -1;
}
if((sock=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,WSA_FLAG_MULTIPOINT_C_LEAF|WSA_FLAG_MULTIPOINT_D_LEAF|
WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("socket failed with:%d\n",WSAGetLastError());
WSACleanup();
return -1;
}
// 加入多播组
remote.sin_family = AF_INET;
remote.sin_port = htons(MCASTPORT);
remote.sin_addr.s_addr = inet_addr( MCASTADDR );
if(( sockM = WSAJoinLeaf(sock,(SOCKADDR*)&remote,sizeof(remote),NULL,NULL,NULL,NULL,
JL_BOTH)) == INVALID_SOCKET)
{
printf("WSAJoinLeaf() failed:%d\n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return -1;
}
// 发送多播数据,当用户在控制台输入"QUIT"时退出。
while(1)
{
printf("SEND : ");
scanf("%s",sendbuf);
if( sendto(sockM,(char*)sendbuf,strlen(sendbuf),0,(struct
sockaddr*)&remote,sizeof(remote))==SOCKET_ERROR)
{
printf("sendto failed with: %d\n",WSAGetLastError());
closesocket(sockM);
closesocket(sock);
WSACleanup();
return -1;
}
if(strcmp(sendbuf,"QUIT")==0 || strcmp(sendbuf, "quit")==0)
break;
Sleep(500);
}
closesocket(sockM);
closesocket(sock);
WSACleanup();
return 0;
}
-----------------------------------------Receiver.c
#include "stdafx.h"
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#define MCASTADDR "224.0.1.0" //本例使用的多播组地址。
#define MCASTPORT 6701 //绑定的本地端口号。
#define BUFSIZE 1024 //接收数据缓冲大小。
#pragma comment(lib, "Ws2_32.lib")
int main(int argc, char* argv[])
{
struct sockaddr_in local;
struct sockaddr_in remote;
struct sockaddr_in from;
SOCKET sock,sockM;
TCHAR recvbuf[BUFSIZE];
/*struct ip_mreq mcast; // Winsock1.0 */
int len = sizeof(struct sockaddr_in);
int ret;
//初始化WinSock2.2
WSADATA wsd;
if( WSAStartup( MAKEWORD(2,2),&wsd) != 0 )
{
printf("WSAStartup() failed\n");
return -1;
}
/*创建一个SOCK_DGRAM类型的SOCKET
其中,WSA_FLAG_MULTIPOINT_C_LEAF表示IP多播在控制面层上属于"无根"类型;
WSA_FLAG_MULTIPOINT_D_LEAF表示IP多播在数据面层上属于"无根",有关控制面层和
数据面层有关概念请参阅MSDN说明。*/
if((sock=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,
WSA_FLAG_MULTIPOINT_C_LEAF|WSA_FLAG_MULTIPOINT_D_LEAF|WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("socket failed with:%d\n",WSAGetLastError());
WSACleanup();
return -1;
}
//将sock绑定到本机某端口上。
local.sin_family = AF_INET;
local.sin_port = htons(MCASTPORT);
local.sin_addr.s_addr = htonl(INADDR_ANY);
if( bind(sock,(struct sockaddr*)&local,sizeof(local)) == SOCKET_ERROR )
{
printf( "bind failed with:%d \n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return -1;
}
//加入多播组
remote.sin_family = AF_INET;
remote.sin_port = htons(MCASTPORT);
remote.sin_addr.s_addr = inet_addr( MCASTADDR );
/* Winsock1.0 */
/*
mcast.imr_multiaddr.s_addr = inet_addr(MCASTADDR);
mcast.imr_interface.s_addr = INADDR_ANY;
if(
setsockopt(sockM,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char*)&mcast,sizeof(mcast))
== SOCKET_ERROR)
{
printf("setsockopt(IP_ADD_MEMBERSHIP) failed:%d\n",WSAGetLastError());
closesocket(sockM);
WSACleanup();
return -1;
}
*/
/* Winsock2.0*/
if(( sockM = WSAJoinLeaf(sock,(SOCKADDR*)&remote,sizeof(remote),NULL,NULL,NULL,NULL,JL_BOTH)) == INVALID_SOCKET)
{
printf("WSAJoinLeaf() failed:%d\n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return -1;
}
//接收多播数据,当接收到的数据为"QUIT"时退出。
while(1)
{
if(( ret = recvfrom(sock,recvbuf,BUFSIZE,0,(struct sockaddr*)&from,&len)) == SOCKET_ERROR)
{
printf("recvfrom failed with:%d\n",WSAGetLastError());
closesocket(sockM);
closesocket(sock);
WSACleanup();
return -1;
}
if( strcmp(recvbuf,"QUIT") == 0 )
break;
else
{
recvbuf[ret] = '\0';
printf("RECV:' %s ' FROM <%s> \n",recvbuf,inet_ntoa(from.sin_addr));
}
}
closesocket(sockM);
closesocket(sock);
WSACleanup();
return 0;
}
请问一下使用预留多播地址为224.0.1.0~238.255.255.255,可用于全球范围(如Internet)或网络协议 为什么不能在英特网上组播呢?请知道的高手指教
设想一个例子,
假设你加入了多播组224.0.1.x,你想通过Internet组播,这就要求TTL值无穷大。离你最近的路由器将你加入x组的信息发送给相邻的路由器,下一路由器又将信息继续传递出去。由于TTL的无穷大这个信息将全球范围内传递,结果是你导致了全球网络的瘫痪。
&nTTL, sizeof(nTTL),
NULL, 0,
(PULONG)&cbRet,
NULL, NULL);