UDP广播组播通信
广播通信方式
数据包发送方式只有一个接收方,称为单播
如果同时发送给局域网内所有主机,称为广播。
只有用户数据报(使用UDP协议)套接字才能广播。
广播发送流程:
1)、创建发送用户数据报套接字
2)、缺省创建的套接字不允许广播数据包,需要设置属性。//setsockopt() 可以设置套接字属性
3)、接受方地址定为广播地址
4)、指定端口信息
5)、发送数据包
6)、关闭套接字
发送流程代码实现:
数据包发送方式只有一个接收方,称为单播
如果同时发送给局域网内所有主机,称为广播。
只有用户数据报(使用UDP协议)套接字才能广播。
广播发送流程:
1)、创建发送用户数据报套接字
2)、缺省创建的套接字不允许广播数据包,需要设置属性。//setsockopt() 可以设置套接字属性
3)、接受方地址定为广播地址
4)、指定端口信息
5)、发送数据包
6)、关闭套接字
发送流程代码实现:
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
int main ()
{
//socket
int sendFd = socket ( PF_INET , SOCK_DGRAM , 0 ); //创建发送用户数据报套接字
if ( sendFd < 0 )
{
perror ( "socket error!" );
return - 1 ;
}
printf ( "socket ok!\n" );
//setsockopt
int on = 1 ;
setsockopt ( sendFd , SOL_SOCKET , SO_BROADCAST , & on , sizeof ( on )); //setsockopt() 可以设置套接字属性
struct sockaddr_in recvAddr = { 0 };
recvAddr . sin_family = PF_INET ;
recvAddr . sin_port = htons ( 9999 ); //指定端口信息
recvAddr . sin_addr . s_addr = inet_addr ( "192.168.3.255" ); //接受方地址定为广播地址
//sendto
char buf [ 1024 ] = { 0 };
gets ( buf );
sendto ( sendFd , buf , sizeof ( buf ), 0 , ( struct sockaddr *)& recvAddr , sizeof ( recvAddr )); //数据发送
//close
close ( sendFd ); //关闭套接字
return 0 ;
}
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
int main ()
{
//socket
int sendFd = socket ( PF_INET , SOCK_DGRAM , 0 ); //创建发送用户数据报套接字
if ( sendFd < 0 )
{
perror ( "socket error!" );
return - 1 ;
}
printf ( "socket ok!\n" );
//setsockopt
int on = 1 ;
setsockopt ( sendFd , SOL_SOCKET , SO_BROADCAST , & on , sizeof ( on )); //setsockopt() 可以设置套接字属性
struct sockaddr_in recvAddr = { 0 };
recvAddr . sin_family = PF_INET ;
recvAddr . sin_port = htons ( 9999 ); //指定端口信息
recvAddr . sin_addr . s_addr = inet_addr ( "192.168.3.255" ); //接受方地址定为广播地址
//sendto
char buf [ 1024 ] = { 0 };
gets ( buf );
sendto ( sendFd , buf , sizeof ( buf ), 0 , ( struct sockaddr *)& recvAddr , sizeof ( recvAddr )); //数据发送
//close
close ( sendFd ); //关闭套接字
return 0 ;
}
广播接收流程:
1)、创建接受用户数据报套接字
2)、绑定本机IP地址和端口号 //绑定的端口必须和发送方指定的端口相同
3)、等待接收数据
4)、关闭接收套接字
接受流程代码实现:
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
intmain()
{
//socket
intrecvFd=socket(PF_INET,SOCK_DGRAM,0); //创建接受用户数据报套接字
if(recvFd<0)
{
perror("socket error!");
return-1;
}
printf("socket ok!\n");
structsockaddr_inrecvAddr={0};
recvAddr.sin_family=PF_INET;
recvAddr.sin_port=htons(9999);
recvAddr.sin_addr.s_addr=htonl(INADDR_ANY);//绑定本机IP地址和端口号 绑定的端口必须和发送方指定的端口相同
//bind
intret=bind(recvFd,(structsockaddr*)&recvAddr,sizeof(recvAddr));
if(ret<0)
{
perror("bind error!");
return-1;
}
printf("bind ok!\n");
charbuf[1024]={0};
//recvfrom
recvfrom(recvFd,buf,sizeof(buf),0,NULL,NULL);//等待接收数据
printf("recv:%s\n",buf);
//close
close(recvFd);//关闭接收套接字
return 0 ;
}
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
intmain()
{
//socket
intrecvFd=socket(PF_INET,SOCK_DGRAM,0); //创建接受用户数据报套接字
if(recvFd<0)
{
perror("socket error!");
return-1;
}
printf("socket ok!\n");
structsockaddr_inrecvAddr={0};
recvAddr.sin_family=PF_INET;
recvAddr.sin_port=htons(9999);
recvAddr.sin_addr.s_addr=htonl(INADDR_ANY);//绑定本机IP地址和端口号 绑定的端口必须和发送方指定的端口相同
//bind
intret=bind(recvFd,(structsockaddr*)&recvAddr,sizeof(recvAddr));
if(ret<0)
{
perror("bind error!");
return-1;
}
printf("bind ok!\n");
charbuf[1024]={0};
//recvfrom
recvfrom(recvFd,buf,sizeof(buf),0,NULL,NULL);//等待接收数据
printf("recv:%s\n",buf);
//close
close(recvFd);//关闭接收套接字
return 0 ;
}
组播通信方式
单播方式只能发送给一个接收方
广播方式发送给所有主机。过多的广播会大量占用网络带宽,造成广播风暴,影响正常的通信
组播又称为多播,是一种折中的方式,只有加入某个多播组的主机才能就收到数据。
多播方式既可以发送给多个主机,又能避免像广播一样带来过多的负载(每台主机要到传输层才能判断广播包是否要处理)
组播发送流程:
1)、创建用户数据包套接字
2)、接收方地址指定为组播地址
3)、指定端口号信息
4)、发送数据包
5)、关闭套接字
广播方式发送给所有主机。过多的广播会大量占用网络带宽,造成广播风暴,影响正常的通信
组播又称为多播,是一种折中的方式,只有加入某个多播组的主机才能就收到数据。
多播方式既可以发送给多个主机,又能避免像广播一样带来过多的负载(每台主机要到传输层才能判断广播包是否要处理)
组播发送流程:
1)、创建用户数据包套接字
2)、接收方地址指定为组播地址
3)、指定端口号信息
4)、发送数据包
5)、关闭套接字
组播发送流程代码:
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
int main ()
{
//socket
int sendFd = socket ( PF_INET , SOCK_DGRAM , 0 ); //创建用户数据包套接字
if ( sendFd < 0 )
{
perror ( "socket error!" );
return - 1 ;
}
struct sockaddr_in recvAddr = { 0 };
recvAddr . sin_family = PF_INET ;
recvAddr . sin_port = htons ( 9999 ); //指定端口号信息
recvAddr . sin_addr . s_addr = inet_addr ( "224.10.10.1" ); //接收方地址指定为组播地址
char buf [ 1024 ] = { 0 };
gets ( buf );
//sendto
sendto ( sendFd , buf , sizeof ( buf ), 0 , ( struct sockaddr *)& recvAddr , sizeof ( recvAddr )); //发送数据包
//close
close ( sendFd ); //关闭套接字
return 0 ;
}
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
int main ()
{
//socket
int sendFd = socket ( PF_INET , SOCK_DGRAM , 0 ); //创建用户数据包套接字
if ( sendFd < 0 )
{
perror ( "socket error!" );
return - 1 ;
}
struct sockaddr_in recvAddr = { 0 };
recvAddr . sin_family = PF_INET ;
recvAddr . sin_port = htons ( 9999 ); //指定端口号信息
recvAddr . sin_addr . s_addr = inet_addr ( "224.10.10.1" ); //接收方地址指定为组播地址
char buf [ 1024 ] = { 0 };
gets ( buf );
//sendto
sendto ( sendFd , buf , sizeof ( buf ), 0 , ( struct sockaddr *)& recvAddr , sizeof ( recvAddr )); //发送数据包
//close
close ( sendFd ); //关闭套接字
return 0 ;
}
组播接收流程:
1)、创建用户数据报套接字
2)、加入多播组
3)、绑定本机IP地址和端口号(绑定的端口号必须和发送指定的端口号相同)
4)、等待接收数据
5)、关闭套接字
1)、创建用户数据报套接字
2)、加入多播组
3)、绑定本机IP地址和端口号(绑定的端口号必须和发送指定的端口号相同)
4)、等待接收数据
5)、关闭套接字
组播接受代码实现
:
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
int main ()
{
//socket
int recvFd = socket ( PF_INET , SOCK_DGRAM , 0 ); //创建用户数据报套接字
if ( recvFd < 0 )
{
perror ( "socket error" );
return - 1 ;
}
printf ( "socket ok!\n" );
//join in multicast group
struct ip_mreq mreq = { 0 };
mreq . imr_multiaddr . s_addr = inet_addr ( "224.10.10.1" ); //加入多播组
mreq . imr_interface . s_addr = htonl ( INADDR_ANY );
setsockopt ( recvFd , IPPROTO_IP , IP_ADD_MEMBERSHIP , & mreq , sizeof ( mreq ));
//bind
struct sockaddr_in recvAddr = { 0 };
recvAddr . sin_family = PF_INET ;
recvAddr . sin_port = htons ( 9999 );
recvAddr . sin_addr . s_addr = htonl ( INADDR_ANY ); //绑定本机IP地址和端口号(绑定的端口号必须和发送指定的端口号相同)
int ret = bind ( recvFd , ( struct sockaddr *)& recvAddr , sizeof ( recvAddr ));
if ( ret < 0 )
{
perror ( "bind error!" );
close ( recvFd );
return - 1 ;
}
//recvfrom
char buf [ 1024 ] = { 0 };
recvfrom ( recvFd , buf , sizeof ( buf ), 0 , NULL , NULL ); //等待接收数据
printf ( "recv %s\n" , buf );
//close
close ( recvFd ); //关闭接收套接字
return 0 ;
}
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
int main ()
{
//socket
int recvFd = socket ( PF_INET , SOCK_DGRAM , 0 ); //创建用户数据报套接字
if ( recvFd < 0 )
{
perror ( "socket error" );
return - 1 ;
}
printf ( "socket ok!\n" );
//join in multicast group
struct ip_mreq mreq = { 0 };
mreq . imr_multiaddr . s_addr = inet_addr ( "224.10.10.1" ); //加入多播组
mreq . imr_interface . s_addr = htonl ( INADDR_ANY );
setsockopt ( recvFd , IPPROTO_IP , IP_ADD_MEMBERSHIP , & mreq , sizeof ( mreq ));
//bind
struct sockaddr_in recvAddr = { 0 };
recvAddr . sin_family = PF_INET ;
recvAddr . sin_port = htons ( 9999 );
recvAddr . sin_addr . s_addr = htonl ( INADDR_ANY ); //绑定本机IP地址和端口号(绑定的端口号必须和发送指定的端口号相同)
int ret = bind ( recvFd , ( struct sockaddr *)& recvAddr , sizeof ( recvAddr ));
if ( ret < 0 )
{
perror ( "bind error!" );
close ( recvFd );
return - 1 ;
}
//recvfrom
char buf [ 1024 ] = { 0 };
recvfrom ( recvFd , buf , sizeof ( buf ), 0 , NULL , NULL ); //等待接收数据
printf ( "recv %s\n" , buf );
//close
close ( recvFd ); //关闭接收套接字
return 0 ;
}