广播和多播只能使用UDP,两者不能够用TCP。
一个IP地址由网络号和主机号组成。所有主机号部分为全1的IP地址是广播地址。
这是广播的原理图。
总结:
应用程序只能通过UDP方式发送广播。
一般情况下,如果调用sendto,只能向非广播地址发送数据报。如果要发送广播数据报,必须告诉内核,可以通过设置SO_BROADCAST套接口选项来做到这一点。
服务器端:
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <stdio.h>
#define BUFLEN 255
void getcurtime(char *curtime)
{
time_t tm;
time(&tm);
snprintf(curtime,BUFLEN,"%s\n",ctime(&tm));
}
int main(int argc,char **argv)
{
struct sockaddr_in peeraddr;
int sockfd,on=1;
int num,i;
char msg[BUFLEN+1];
if(argc!=3){
printf("usage:%s<ip address><port>\n",argv[0]);
exit(0);
}
sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd<0){
fprintf(stderr,"socket creating error in tserv.c\n");
exit(1);
}
setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&on,sizeof(int));
memset(&peeraddr,0,sizeof(struct sockaddr_in));
peeraddr.sin_family=AF_INET;
if(inet_pton(AF_INET,argv[1],&peeraddr.sin_addr)<=0){
printf("Wrong dest IP address\n");
exit(0);
}
peeraddr.sin_port=htons(atoi(argv[2]));
for(;;){
getcurtime(msg);
int a;
a=sendto(sockfd,msg,strlen(msg),0,(struct sockaddr *)&peeraddr,sizeof(struct sockaddr_in));
printf("%d",a);
fflush(stdout);
sleep(3);
}
}
客户端:
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#define BUFLEN 255
int main(int argc,char** argv)
{
struct sockaddr_in localaddr;
int sockfd,n;
char msg[BUFLEN+1];
if(argc!=2){
printf("usage:%s<port>\n",argv[0]);
exit(0);
}
sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd<0){
fprintf(stderr,"socket creating error in tcli.c\n");
exit(1);
}
memset(&localaddr,0,sizeof(struct sockaddr_in));
localaddr.sin_port=htons(atoi(argv[1]));
localaddr.sin_addr.s_addr=htonl(INADDR_ANY);
int opt = SO_REUSEADDR;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
if(bind(sockfd,(struct sockaddr *)&localaddr,sizeof(struct sockaddr_in))<0){
fprintf(stderr,"bind error in tcli.c\n");
exit(2);
}
n=read(sockfd,msg,BUFLEN);
if(n==-1){
fprintf(stderr,"read error in tcli.c\n");
exit(3);
}
else{
msg[n]=0;
printf("%s",msg);
}
}