目录
步骤2:组读请求(0,1,“a.txt”,0,"netascii",0),发送给服务器
步骤2:组写请求(0,2,“a.txt”,0,"netascii",0),发送给服务器
数据包格式:
一、下载
步骤1:创建udp套接字
int scokfd=socket(AF_INET,SOCK_DGRAM,0);
if(scokfd<0)
{
printf("套接字创建失败\n");
return -1;
}
else
printf("套接字创建成功\n");
步骤2:组读请求(0,1,“a.txt”,0,"netascii",0),发送给服务器
struct sockaddr_in ser_ddr;
bzero(&ser_ddr,sizeof(ser_ddr));
ser_ddr.sin_family=AF_INET;
ser_ddr.sin_port=htons(69);
inet_pton(AF_INET,"10.36.145.87",(void*)&ser_ddr.sin_addr);
char buf[64]="";
int buf_len=sprintf(buf,"%c%c%s%c%s%c",0,1,"a.txt",0,"netascii",0);
sendto(scokfd,buf,buf_len,0,(struct sockaddr*)&ser_ddr,sizeof(ser_ddr));
步骤3:创建并打开本地文件
步骤4:循环接受数据buf
如果buf长度<516结束读取
查看buf[1]==3 "数据包" 写文件
回复 "ACK" buf[1]==4
buf[1]==5 "ERROR" ;break;
int fd =open("./a.txt",O_RDWR|O_CREAT,0666);
if(fd<0)
{
perror(open);
return -1;
}
char recv_buf[1024]="";
int recv_len=0;
struct sockaddr_in from_addr;
socklen_t addrlen=sizeof(from_addr);
while (1)
{
bzero(&from_addr,sizeof(from_addr));
recv_len=recvfrom(scokfd,recv_buf,sizeof(recv_buf),0,(struct sockaddr*)&from_addr,&addrlen);
if(recv_buf[1]==5)
{
printf("error:%s\n",recv_buf+4);
break;
}
else if(recv_buf[1]==3)
{
write(fd,recv_buf+4,recv_len-4);
//回复ACK
recv_buf[1]=4;
sendto(scokfd,recv_buf,4,0,(struct sockaddr *)&from_addr,sizeof(from_addr));
if(recv_len<516)
break;
}
}
步骤5:关闭文件描述符,关闭套接字
close(scokfd);
close(fd);
二、上传
步骤1:创建udp套接字
int sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd<0){
printf("创建失败\n");
return 0;
}
else{
printf("创建成功 %d\n",sockfd);
}
步骤2:组写请求(0,2,“a.txt”,0,"netascii",0),发送给服务器
struct sockaddr_in ser_addr;
bzero(&ser_addr,sizeof(ser_addr));
ser_addr.sin_family=AF_INET;
ser_addr.sin_port=htons(69);
inet_pton(AF_INET,"10.36.145.87",(void *)&ser_addr.sin_addr);
char buf[64]="";
int buf_len=sprintf(buf,"%c%c%s%c%s%c",0,2,"a.txt",0,"netascii",0);
sendto(sockfd,buf,buf_len,0,(struct sockaddr *)&ser_addr,sizeof(ser_addr));
步骤3:打开本地文件a.txt
int fd = open("./a.txt",O_RDWR);
if(fd<0){
perror("open");
return 0;
}
步骤4:循环接受数据buf
查看buf[0~1]==4------buf[2~3]=块编号;读文件,回复数据包seddbuf=(0,3,buf[2~3]+1,读文件512)
buf[1]==5;break;
char rcv_buf[1024]="";
int rcv_buf_len=0;
unsigned short p_num=0;
struct sockaddr_in from_addr;//服务器ip和服务器的临时端口
socklen_t addrlen=sizeof(from_addr);
while(1){
bzero(&from_addr,sizeof(from_addr));
recvfrom(sockfd, rcv_buf, sizeof(rcv_buf),0,(struct sockaddr*)&from_addr,&addrlen);
if(rcv_buf[1]==5)//差错
{
printf("error:%s\n",rcv_buf+4);
break;
}
else if(rcv_buf[1]==4)//ACK
{
//读本地文件
rcv_buf_len= read(fd,rcv_buf+4,512);
rcv_buf[1]=3;
p_num=ntohs(*(unsigned short *)(rcv_buf+2));//取rcv_buf的3~4字节并保存到主机
*(unsigned short *)(rcv_buf+2)=htons(p_num+1);
//将ack包的编号+1,赋值给数据包0 4 0 x-------0 3 0 x+1 512byte
printf("即将发送数据包编号:%d\n",p_num+1);
sendto(sockfd,rcv_buf,rcv_buf_len+4,0,(struct sockaddr *)&from_addr,sizeof(from_addr));
if(rcv_buf_len<512)
break;
}
else;
}
步骤5:关闭文件描述符,关闭套接字
close(sockfd);
close(fd);