简单文件传输协议
1.服务器在69号端口等待客户端的请求
2.服务器若批准此请求,则使用临死端口与客户端进行通信
3.每个数据包的编号都有变化(从1开始)
4.每个数据包都要得到ACK的确认如果出现超时,则需要重新发送最后的包(数据或ACK)
6.小于512Byte的数据意味着传输结束
![](https://img.haomeiwen.com/i1607463/0846f416209cacd4.png)
示例代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<pthread.h>
#include<arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <fcntl.h>void sys_err(const char *str)
{
perror(str);
exit(1);
}int main(int argc,char *argv[])
{
int skfd = socket(AF_INET,SOCK_DGRAM,0);
int fd = open("a.txt",O_WRONLY|O_CREAT|O_TRUNC,0664);
unsigned char cmd[512] = "";
int len = sprintf(cmd,"%c%c%s%c%s%c",0,1,"a.txt",0,"octet",0);//下载文件请求报文
struct sockaddr_in ser_addr,from_addr;
socklen_t from_len = sizeof(from_addr);
bzero(&ser_addr,sizeof(ser_addr));
ser_addr.sin_family = AF_INET;
ser_addr.sin_port = htons(69);//69端口为tftp服务器端口
ser_addr.sin_addr.s_addr = inet_addr("192.168.10.59");sendto(skfd,cmd,len,0,(struct sockaddr *)&ser_addr,sizeof(ser_addr));
int pack_num = 0;
while(1)
{
unsigned char buf[1600] = "";
int size = recvfrom(skfd,buf,sizeof(buf),0,(struct sockaddr *)&from_addr,&from_len);
if(buf[1] == 5){ //5位错误码
printf("err\n");
break;
}else if(buf[1] == 3){ //3为数据包
int num = ntohs(*(unsigned short *)(buf+2));
if(pack_num +1 == num){ //是否为想要的数据包避免数据重复接受
pack_num = num;
write(fd,buf+4,size-4);
}
buf[1] = 4;
sendto(skfd,buf,4,0,(struct sockaddr *)&from_addr,sizeof(from_addr)); //发送回应报文
if(size < 516)
break;
}
}
close(skfd);
close(fd);
return 0;
}
网友评论