TFTP
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#define err(msg) do{fprintf(stderr,"__%d__",__LINE__);perror(msg);return -1;}while(0)//有#无分号
#define IP "192.168.31.176"//本机ip 188 ifconfig 查看 ip-192.168.31.176
#define N 128
int main(int argc, const char *argv[])
{
//创建 报式 (udp)套接字
int sfd=socket(AF_INET,SOCK_DGRAM,0);
if(sfd<0)err("socket");
//端口快速重用
int reuse=1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)err("setsockopt");
//补充服务器地址信息结构体---ip 端口
//man 7 ip
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(69);//端口69
sin.sin_addr.s_addr=inet_addr(IP);
//将端口,ip绑定到套接字上---非必要
/* if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin))<0)err("bind");
printf("绑定成功\n");*/
//存储接收到的数据包来自哪里
char str[516]="";
ssize_t res=0;
// 客户端 发送读写请求
char buf[N]="";
short int *pa=(short int *)buf;
*pa =htons(1);//1-rd 2-wr 客户端发送读命令给客户端
char *pb=(char*)(pa +1);
char filename[50]="";
printf("请输入文件名:");
scanf("%s",filename);
int bytes=sprintf(buf,"%c%c%s%c%s%c",0,1,filename,0,"octet",0);
if(sendto(sfd,buf,bytes,0,(struct sockaddr*)&sin,sizeof(sin))<0)err("sendto");//发送请求
//ACK
char ack[4]="";
short int* pack_a=(short int*)ack;
*pack_a=htons(4);
short int* pack_b=pack_a+1;
int fp=open(filename,O_WRONLY|O_CREAT|O_TRUNC,0664);
char txt[512]="";
struct sockaddr_in ccc;
socklen_t addrlen = sizeof(ccc);
while(1)
{
bzero(str,sizeof(str));
//循环接收数据包,
if((res=recvfrom(sfd,str,sizeof(str),0,(struct sockaddr *)&ccc,&addrlen))==-1)err("recvform");
int opert=ntohs(*(short int*)str);//操作符
int num=ntohs(*((short int*)(str+2)));//块编号
printf("opert=%d\tnum=%d\tres=%ld\n",opert,num,res);
// strncpy(txt,str+4,res); 错误 strcpy遇到/0结束 后面是/0
if(opert==3)
{
//写
//write(fp,txt,res-4);
write(fp,str+4,res-4);
//发送ACK
*pack_b=htons(num);
printf("txt.num=%d\n",num);
if(sendto(sfd,ack,sizeof(ack),0,(struct sockaddr*)&ccc,sizeof(ccc))<0)err("sendto");
printf("发送成功\n");
}
else if(opert==5)
{
printf("error:%s\n",(char*)((short int *)str+2));
break;
}
if(res<512)
{
printf("文件拷贝结束\n");break;
}
}
printf("文件下载完成\n");
//关闭套接字
close(sfd);
close(fp);
return 0;
}