1. 完成广播代码
发送端
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#define IP "192.168.196.255"
#define PORT 8888
int main(int argc, const char *argv[])
{
int sfd=socket(AF_INET,SOCK_DGRAM,0);
if(sfd<0){
perror("socket");
return -1;
}
struct sockaddr_in rst;
rst.sin_family=AF_INET;
rst.sin_port=htons(PORT);
rst.sin_addr.s_addr=inet_addr(IP);
int enbroad=1;
int optlen=sizeof(enbroad);
setsockopt(sfd,SOL_SOCKET,SO_BROADCAST,&enbroad,optlen);
int i=0;
char senbuf[]="test\n";
while(1){
sendto(sfd,senbuf,sizeof(senbuf),0,(struct sockaddr *)&rst,sizeof(rst));
sleep(1);
}
return 0;
}
接收端
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define IP "192.168.196.255"
#define PORT 8888
int main(int argc, const char *argv[])
{
int sfd=socket(AF_INET,SOCK_DGRAM,0);
if(sfd<0){
perror("socket");
return -1;
}
struct sockaddr_in urst;
urst.sin_family=AF_INET;
urst.sin_port=htons(PORT);
urst.sin_addr.s_addr=inet_addr(IP);
socklen_t rstlen=sizeof(urst);
if(bind(sfd,(struct sockaddr *)&urst,rstlen)){
perror("bind");
return -1;
}
char recbuf[50];
int reclen=0;
while(1){
reclen=recvfrom(sfd,recbuf,50,0,NULL,0);
fwrite(recbuf,1,reclen,stdout);
fflush(stdout);
}
return 0;
}
2. 完成tftp的上传下载
tftp模型
下载
上传
tftp协议语句结构
tftp.c
#include <stdio.h>
#include "tftp.h"
void menu()
{
char opt='a';
system("clear");
printf("服务器IP地址:");
char IP[16]="";
fgets(IP,15,stdin);
IP[strlen(IP)-1]=0;
char filename[100]="";
system("clear");
while(1){
system("ls");
printf("----------\n");
printf("-1.下载---\n");
printf("-2.上传---\n");
printf("-3.退出---\n");
printf("----------\n");
printf(":");
scanf(" %c",&opt);
while(getchar()!='\n');
switch(opt)
{
case '1':
bzero(filename,100);
printf("下载文件名:");
fgets(filename,100,stdin);
filename[strlen(filename)-1]=0; // 去结尾回车符,下同
download(IP,filename);
system("clear");
printf("下载完成\n");
break;
case '2':
bzero(filename,100);
printf("上传文件名:");
fgets(filename,100,stdin);
filename[strlen(filename)-1]=0;
upload(IP,filename);
system("clear");
printf("上传完成\n");
break;
case '3':
return;
break;
}
}
}
// 构建请求指令
char *questmd(const char *IP,const char *filename)
{
int namelen=strlen(filename);
char *reqmd=(char *)malloc(namelen+9);
bzero(reqmd,namelen+9);
reqmd[1]=1;
strcpy(reqmd+2,filename);
strcpy(reqmd+3+namelen,"octet");
/*
for(int i=0;i<namelen+9;i++){
printf("%d ",reqmd[i]);
}
*/
return reqmd;
}
// 下载
int download(const char *IP,const char *filename)
{
char *qmd=questmd(IP,filename);
int filenamelen = strlen(filename);
// 准备文件进行拷贝
int fwd=open(filename,O_WRONLY|O_CREAT|O_TRUNC,0777);
if(fwd<0){
MSG_ERR("open");
}
// 创建套接字
int urd=socket(AF_INET,SOCK_DGRAM,0);
// tftp服务器地址信息结构体
struct sockaddr_in ust;
ust.sin_family=AF_INET;
ust.sin_port=htons(PORT);
ust.sin_addr.s_addr=inet_addr(IP);
// 接受数据包
char recbuf[516];
int reclen=516;
// ACK
char ackbuf[4];
bzero(ackbuf,4);
ackbuf[1]=4;
short ackrec=0; // 记录快编号,复制重复接受
struct sockaddr_in tempust;
int templen;
sendto(urd,qmd,filenamelen+9,0,(struct sockaddr *)&ust,sizeof(ust));
do{
bzero(recbuf,516);
reclen=recvfrom(urd,recbuf,516,0,(struct sockaddr*)&tempust,&templen);
// printf("%d___%d\n",ackrec,ntohs(*(short int *)(recbuf+2)));
if(ackrec<ntohs(*(short int *)(recbuf+2))){ // 对比块编号防止重复下载
ackrec=ntohs(*(short int *)(recbuf+2));
ackbuf[2]=recbuf[2];ackbuf[3]=recbuf[3];
write(fwd,recbuf+4,reclen-4);
}
sendto(urd,ackbuf,4,0,(struct sockaddr*)&tempust,templen);
}while(reclen==516);
close(fwd);
close(urd);
return 0;
}
// 上传
int upload(const char *IP,const char *filename)
{
char *qmd=questmd(IP,filename);
qmd[1]=2;
int filenamelen=strlen(filename);
int frd=open(filename,O_RDONLY);
if(frd <0){
MSG_ERR("open");
}
// 创建套接字
int uwd=socket(AF_INET,SOCK_DGRAM,0);
// tftp服务器地址信息结构体
struct sockaddr_in ust;
ust.sin_family=AF_INET;
ust.sin_port=htons(PORT);
ust.sin_addr.s_addr=inet_addr(IP);
// 发送缓存
char senbuf[516];
senbuf[0]=0;senbuf[1]=3;
// 读取文件长度
int redlen=512;
// 接受ACK
char ackbuf[4];
bzero(ackbuf,4);
short blocknum=1; // 快编号
// tftp临时端口
struct sockaddr_in tempust;
int templen;
int sendlen = sendto(uwd,qmd,filenamelen+9,0,(struct sockaddr *)&ust,sizeof(ust));
do{
printf("%d_____%d\n",blocknum,ntohs(*(short *)(ackbuf+2)));
recvfrom(uwd,ackbuf,4,0,(struct sockaddr *)&tempust,&templen);
if((blocknum-1)==ntohs(*(short *)(ackbuf+2))){ // 对比ACK返回块编号,确保上传数据被接收
bzero(senbuf+2,514);
redlen = read(frd,senbuf+4,512);
*(short int *)(senbuf+2)=htons(blocknum);
blocknum++;
}
sendto(uwd,senbuf,redlen+4,0,(struct sockaddr *)&tempust, templen);
}while(redlen==512);
}
tftp.h
#ifndef __TFTP_H__
#define __TFTP_H__
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#define MSG_ERR(msg) {\
printf("%d",__LINE__);\
perror(msg);\
return -1;\
}
#define PORT 69
// 目录
void menu();
// 构建请求指令
char *questmd(const char *IP,const char *filename);
// 下载
int download(const char *IP,const char *filename);
// 上传
int upload(const char *IP,const char *filename);
#endif
main.c
#include <stdio.h>
#include "tftp.h"
int main(int argc, const char *argv[])
{
menu();
return 0;
}