1、广播
广播接收端:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__);\
perror(msg);\
}while(0)
#define PORT 8888
#define IP "192.168.31.255"
int main(int argc, const char *argv[])
{
int sfd = socket(AF_INET,SOCK_DGRAM,0);//创建报式套接字
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
struct sockaddr_in sin;//填充服务器地址信息结构体
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);//端口号的网络字节序;1024~49151
sin.sin_addr.s_addr = inet_addr(IP);//广播IP地址
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin)) < 0 )//绑定IP地址和端口号
{
ERR_MSG("bind");
return -1;
}
printf("bind success\n");
struct sockaddr_in sep;
socklen_t addrlen =sizeof(sep);
char buf[128]="";
ssize_t res = 0;
while(1)
{
res = recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sep,&addrlen);//接受数据
if(res < 0)
{
ERR_MSG("recvfrom");
return -1;
}
printf("[%s|%d]n :%s\n",inet_ntoa(sep.sin_addr),ntohs(sep.sin_port),buf);
}
close(sfd);
return 0;
}
广播发送端:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__);\
perror(msg);\
}while(0)
#define PORT 8888
#define IP "192.168.31.255"
int main(int argc, const char *argv[])
{
int sfd = socket(AF_INET,SOCK_DGRAM,0);//创建报式套接字
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
int reuse=1;
if(setsockopt(sfd,SOL_SOCKET,SO_BROADCAST,&reuse,sizeof(reuse)) < 0)
{
ERR_MSG("");
return -1;
}
struct sockaddr_in sin;//填充广播的信息结构体
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);//端口号的网络字节序;1024~49151
sin.sin_addr.s_addr = inet_addr(IP);//IP
char buf[128]="";
struct sockaddr_in sep;
socklen_t addrlen =sizeof(sep);
while(1)
{
bzero(buf,sizeof(buf));
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]=0;
if(sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin)) < 0)
{
ERR_MSG("sendto");
return -1;
}
}
close(sfd);
return 0;
}
2、组播
组播发送端:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__);\
perror(msg);\
}while(0)
#define PORT 8888
int main(int argc, const char *argv[])
{
int sfd = socket(AF_INET,SOCK_DGRAM,0);//创建报式套接字
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
int reuse = 1;//
if(setsockopt(sfd,SOL_SOCKET,SO_BROADCAST,&reuse,sizeof(reuse)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
struct sockaddr_in sin;//填充服务器地址信息结构体
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);//端口号的网络字节序;1024~49151
sin.sin_addr.s_addr = inet_addr("224.1.2.3");//("224.7.7.7");//广播IP
char buf[128]="";
while(1)
{
//发送
bzero(buf,sizeof(buf));
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = 0;
if(sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin)) < 0)
{
ERR_MSG("sendto");
return -1;
}
}
close(sfd);
return 0;
}
组播接收端:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <net/if.h>
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__);\
perror(msg);\
}while(0)
#define PORT 8888
int main(int argc, const char *argv[])//接收方
{
int sfd = socket(AF_INET,SOCK_DGRAM,0);//创建报式套接字
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
//加入多播组setsockopt
struct ip_mreqn mq;
mq.imr_multiaddr.s_addr = inet_addr("224.1.2.3");//("224.7.7.7");//组播IP
mq.imr_address.s_addr = inet_addr("192.168.31.30");//本机IP
mq.imr_ifindex = if_nametoindex("ens33");//设备索引号0/2
if(setsockopt(sfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mq,sizeof(mq)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
struct sockaddr_in sin;//填充接收方地址信息结构体
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);//端口号的网络字节序;1024~49151
sin.sin_addr.s_addr = inet_addr("224.1.2.3");//("224.7.7.7");//组播IP
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin)) < 0)
{
ERR_MSG("bind");
return -1;
}
printf("bind success\n");
char buf[128]="";
struct sockaddr_in cin;
socklen_t addrlen=sizeof(cin);
while(1)
{
//接收
bzero(buf,sizeof(buf));
if(recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,&addrlen) < 0)
{
ERR_MSG("recvfrom");
return -1;
}
printf("[%s | %d]:%s\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),buf);
}
close(sfd);
return 0;
}
3、tftp客户端
下载:
//下载
int do_download(int sfd,struct sockaddr_in sin)
{
char filename[20] = "";
printf("请输入要下载的文件名>>>");
fgets(filename, sizeof(filename), stdin);
filename[strlen(filename)-1] = 0;
//读写请求
char buf[516]={0};
//操作码 1 2个字节
char* ptr = buf;
unsigned short* pa=(unsigned short*)ptr;
*pa=htons(1);//下载操作码
//文件名
char* p1=ptr+2;
strcpy(p1,filename);
//模式
char* p2=p1+strlen(p1)+1;
strcpy(p2,"octet");
//长度
int size=9+strlen(p1);
if(sendto(sfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin)) < 0)
{
ERR_MSG("sendto");
return -1;
}
socklen_t addrlen = sizeof(sin);
// char temp[513] = 0;//存储接受到的数据
ssize_t res = 0;//接受返回包的长度
unsigned short num = 0;//块编号
//打开文件
int fd;
int flag = 0;
while(1)
{
//接受服务器返回的包
bzero(buf,sizeof(buf));
if((res = recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&addrlen)) < 0)
{
ERR_MSG("recvfrom");
return -1;
}
if(3 == buf[1])//数据包操作码
{
if(0 == flag)//打开文件
{
fd = open(filename,O_WRONLY|O_CREAT|O_TRUNC,0664);
if(fd < 0)
{
ERR_MSG("open");
return -1;
}
flag = 1;
}
//判断块编号
if(num+1 == ntohs(*(unsigned short*)(buf+2)))
{
num++;
//提取数据到文件中
if(write(fd,buf+4,res-4) < 0)
{
ERR_MSG("write");
}
//回复ACK
buf[1]=4;
if(sendto(sfd,buf,4,0,(struct sockaddr*)&sin,sizeof(sin)) < 0)
{
ERR_MSG("sendto");
return -1;
}
//当数据小于512时,下载结束
if(res < 516)
{
printf("-----文件下载完毕-----\n");
break;
}
}
else
{
printf("数据包编号错误,请检查网络环境\n");
break;
}
}
else if(5 == buf[1])//错误操作码
{
printf("----ERROR:%s----\n",buf+4);
return -1;
}
}
close(fd);
return 0;
}