用tftp协议完成客户端从服务器的包下载:
#include <myhead.h>
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__:",__LINE__);\
perror(msg);\
}while(0)#define PORT 69
#define IP "192.168.114.48"int do_download(int cfd,struct sockaddr_in sin);
int do_upload(int cfd,struct sockaddr_in sin);int main(int argc, const char *argv[])
{
//创建报式套接字
int cfd=socket(AF_INET,SOCK_DGRAM,0);
if(cfd == -1){
ERR_MSG("socket");
return -1;
}
printf("socket create success cfd=%d\n",cfd);struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);char choose = 0;
while(1){
system("clear");
printf("----------------------------------\n");
printf("------------1.下载----------------\n");
printf("------------2.上传----------------\n");
printf("------------3.退出----------------\n");
printf("----------------------------------\n");
printf("请输入:");
scanf("%c",&choose);
while(getchar()!=10);switch(choose){
case '1':
do_download(cfd,sin);
break;
case '2':
//do_upload();
break;
case '3':
goto END;
break;
default:
printf("输入错误,请重新输入\n");
}
printf("输入任意字符清屏>>>");
while(getchar()!=10);
}
END:
close(cfd);
return 0;
}int do_download(int cfd,struct sockaddr_in sin){
//组下载数据包
char filename[20]="";
printf("请输入文件名:");
scanf("%s",filename);
char buf[516]="";
while(getchar()!=10);
/*short *p1=(short*)buf;
*p1=htons(1);
char *p2=buf+2;
strcpy(p2,filename);
char *p3=p2+strlen(filename);
*p3=0;
char *p4=p3+1;
strcpy(p4,"octet");int size=4+strlen(filename)+strlen("octet");*/
int size=sprintf(buf,"%c%c%s%c%s%c",0,1,filename,0,"octet",0);
//发送下载请求 sendto
if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin)) == -1){
ERR_MSG("sendto");
return -1;
}
printf("请求发送成功\n");socklen_t addrlen = sizeof(sin);
int fd;
short id=1;
ssize_t res;
while(1){
bzero(buf,sizeof(buf));
//接收数据 recvfrom,接收地址信息
if((res=recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&addrlen)) == -1){
ERR_MSG("recvfrom");
return -1;
}if(buf[1] == 3){
if(*(short*)(buf+2) == htons(1)){
if((fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC,0664)) == -1){
ERR_MSG("open");
return -1;
}
}
if(*(short*)(buf+2) == htons(id)){
if(write(fd,buf+4,res-4) == -1){
ERR_MSG("write");
return -1;
}//组ACK包
buf[1] = 4;//发送ACK sendto
if(sendto(cfd,buf,4,0,(struct sockaddr*)&sin,sizeof(sin)) == -1){
ERR_MSG("sendto");
return -1;
}//判断数据是否小于512个字节,若小于则下载完成
if(res-4<512){
printf("下载完成\n");
break;
}
id++;
}
}
else if(buf[1] == 5){
printf("差错码:%d,差错信息:%s\n",ntohs(*(short*)(buf+2)),buf+4);
break;
}
}
close(fd);
return 0;
}