做tftp协议的客户端的下载与上传功能
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <strings.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
//打印错误信息的宏函数
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__);\
perror(msg);\
}while(0)
#define PORT 69 //1024~49151
#define IP "192.168.31.236" //服务器ip,用ifconfig查看
int main(int argc, const char *argv[])
{
int sfd=socket(AF_INET,SOCK_DGRAM,0);
if(sfd<0)
{
ERR_MSG("socket");
return -1;
}
printf("create socket success\n");
struct sockaddr_in sin;
sin.sin_family =AF_INET;
sin.sin_port =htons(69);
sin.sin_addr.s_addr =inet_addr(argv[1]);
//定义读写请求
char buf[128]="";
char *ptr=buf;
short int *pa=(short int *)ptr;
uint16_t caozuo;
printf("请输入要进行什么操作,1、读 2、写\n");
scanf("%hu",&caozuo);
getchar();
*pa=htons(caozuo);
char *pb=ptr+2;
char file[50]="";
fgets(file,sizeof(file),stdin);
file[strlen(file)-1]=0;
strcpy(pb,file);
char *pc=pb+strlen(pb);
char *pd=pc+1;
strcpy(pd,"octet");
size_t size=2+strlen(pb)+1+5+1;
if(caozuo==1)
{
FILE * fp=fopen(file,"w"); //打开要下载的文件
//发送读请求
if(sendto(sfd,buf,size,0,(struct sockaddr *)&sin,sizeof(sin))<0)
{
ERR_MSG("sendto");
return -1;
}
struct sockaddr_in rcv_addrmsg;
socklen_t addrlen =sizeof(rcv_addrmsg);
//读数据包并发ACK
char rev[516]=""; //数据包
short int i=1; //块编号
char snd[4]=""; //ACK
char ERROR[50]=""; //差错码
while(1)
{
//接收的数据包
bzero(rev,sizeof(rev));
//发送的ACK
char *rtr=snd;
short int *ra=(short int *)rtr;
*ra=htons(4);
short int *rb=ra+1;
*rb=ntohs(i);
//接收数据包
ssize_t res=recvfrom(sfd,rev,sizeof(rev),0,(struct sockaddr*)&rcv_addrmsg,&addrlen);
if(res<0)
{
ERR_MSG("recvfrom");
return -1;
}
if(ntohs(*(short int *)rev)==5)
{
printf("%d:%s\n",ntohs(*(short int *)(rev+2)),rev+4);
}
//块编号连不连续
if(ntohs(*(short int *)(rev+2))!=i)
{
continue;
}
//结束条件
if(res<516)
{
fwrite(rev+4,res-4,1,fp);
sendto(sfd,snd,sizeof(snd),0,(struct sockaddr *)&rcv_addrmsg,addrlen);
break;
}
//正常下载
fwrite(rev+4,res-4,1,fp);
sendto(sfd,snd,sizeof(snd),0,(struct sockaddr *)&rcv_addrmsg,addrlen);
i++;
}
fclose(fp);
}
else if(caozuo==2)
{
FILE * fp=fopen(file,"r"); //打开要下载的文件
//发送写请求
if(sendto(sfd,buf,size,0,(struct sockaddr *)&sin,sizeof(sin))<0)
{
ERR_MSG("sendto");
return -1;
}
struct sockaddr_in snd_addrmsg;
socklen_t addrlen =sizeof(snd_addrmsg);
//发数据包并接收ACK
char snd[516]=""; //数据包
short int i=1; //块编号
char rev[50]=""; //ACK
if(recvfrom(sfd,rev,sizeof(rev),0,(struct sockaddr *)&snd_addrmsg,&addrlen)<0)
{
ERR_MSG("recvfrom");
return -1;
}
while(1)
{
bzero(snd,sizeof(snd));
short int *qa=(short int*)snd;
*qa=htons(3);
short int *qb=qa+1;
*qb=htons(i);
size_t num=fread(snd+4,1,512,fp);
if(num<0)
{
ERR_MSG("fread");
return -1;
}
if(num<512)
{
//发送数据包
if(sendto(sfd,snd,num+4,0,(struct sockaddr*)&snd_addrmsg,addrlen)<0)
{
ERR_MSG("sendto");
return -1;
}
break;
}
//发送数据包
if(sendto(sfd,snd,sizeof(snd),0,(struct sockaddr*)&snd_addrmsg,addrlen)<0)
{
ERR_MSG("sendto");
return -1;
}
ssize_t res=recvfrom(sfd,rev,sizeof(rev),0,(struct sockaddr *)&snd_addrmsg,&addrlen);
/*if(res==5)
{
printf("%d:%s\n",ntohs(*(short int *)(rev+2)),rev+4);
}*/
/*else if(res==4)
{
if(*qb!=*(short int *)(rev+2))
return -1;
}*/
i++;
}
fclose(fp);
}
return 0;
}
做tftp协议的客户端的下载功能
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <strings.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
//打印错误信息的宏函数
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__);\
perror(msg);\
}while(0)
#define PORT 69 //1024~49151
#define IP "192.168.31.236" //服务器ip,用ifconfig查看
int main(int argc, const char *argv[])
{
int sfd=socket(AF_INET,SOCK_DGRAM,0);
if(sfd<0)
{
ERR_MSG("socket");
return -1;
}
printf("create socket success\n");
struct sockaddr_in sin;
sin.sin_family =AF_INET;
sin.sin_port =htons(69);
sin.sin_addr.s_addr =inet_addr(argv[1]);
//定义读请求
char buf[128]="";
char *ptr=buf;
short int *pa=(short int *)ptr;
*pa=htons(1);
char *pb=ptr+2;
char file[50]="";
fgets(file,sizeof(file),stdin);
file[strlen(file)-1]=0;
strcpy(pb,file);
char *pc=pb+strlen(pb);
char *pd=pc+1;
strcpy(pd,"octet");
size_t size=2+strlen(pb)+1+5+1;
//发送读请求
if(sendto(sfd,buf,size,0,(struct sockaddr *)&sin,sizeof(sin))<0)
{
ERR_MSG("sendto");
return -1;
}
struct sockaddr_in rcv_addrmsg;
socklen_t addrlen =sizeof(rcv_addrmsg);
//读数据包并发ACK
char rev[516]=""; //数据包
short int i=1; //块编号
FILE * fp=fopen(file,"w"); //打开要下载的文件
char snd[4]=""; //ACK
while(1)
{
//接收的数据包
bzero(buf,sizeof(rev));
//发送的ACK
char *rtr=snd;
short int *ra=(short int *)rtr;
*ra=htons(4);
short int *rb=ra+1;
*rb=ntohs(i);
//接收数据包
ssize_t res=recvfrom(sfd,rev,sizeof(rev),0,(struct sockaddr*)&rcv_addrmsg,&addrlen);
if(res<0)
{
ERR_MSG("recvfrom");
return -1;
}
//块编号连不连续
if(ntohs(*(short int *)(rev+2))!=i)
{
continue;
}
//结束条件
if(res<516)
{
fwrite(rev+4,res-4,1,fp);
sendto(sfd,snd,sizeof(snd),0,(struct sockaddr *)&rcv_addrmsg,addrlen);
break;
}
//正常下载
fwrite(rev+4,res-4,1,fp);
sendto(sfd,snd,sizeof(snd),0,(struct sockaddr *)&rcv_addrmsg,addrlen);
i++;
}
fclose(fp);
return 0;
}