8.10-网络编程-作业

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 <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>     
//打印错误消息的宏函数
#define ERR_MSG(msg) do{\
	fprintf(stderr,"__%d__",__LINE__);\
	perror(msg);\
}while(0)
#define IP "192.168.31.178"
#define PORT 69
#define FILE_NAME "1.png"
#define MODE "octet"

int main(int argc, const char *argv[])
{
	//套接字
	int sfd = socket(AF_INET,SOCK_DGRAM,0);	
	if(sfd < 0)
	{
		ERR_MSG("socket");
		return -1;
	}
	//服务器地址信息
	struct sockaddr_in cin;
	cin.sin_family = AF_INET;
	cin.sin_port = htons(PORT);
	cin.sin_addr.s_addr = inet_addr(IP);
	char buf[516] = "";
	//读写请求
	char* ptr = buf;     
	short int* pa = (short int*)ptr;   //操作码
	*pa = htons(1);
	char* pb = buf+2;      //文件名
	strcpy(pb,FILE_NAME); 
	char* pc = pb+strlen(pb)+1;//模式
	strcpy(pc,MODE);
	int size = 2+strlen(pb)+1+strlen(pc)+1;

	//发送请求包
	if(sendto(sfd,buf,size,0,(struct sockaddr*)&cin,sizeof(cin)) < 0)
	{
		ERR_MSG("sendto");
		return -1;
	}

	int fd = open(FILE_NAME,O_WRONLY|O_CREAT|O_TRUNC,0664);
	if(fd < 0)
	{
		ERR_MSG("open");
		return -1;
	}

	char *file = (char*)(pa+2);   //指向接收文件的数据的首地址
	short int data;        //数据包的操作码
	short int block;      //数据包的块编号
	int rec_size;         //接收的数据大小
	int size_cin = sizeof(cin);   //服务器地址信息结构体大小
	//循环接收文件数据
	while(1)
	{
		bzero(buf,sizeof(buf));
		//分析接收的数据
		rec_size = recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,&size_cin);
		if(rec_size < 0)
		{
			ERR_MSG("recvfrom");
			return -1;                                                           
		}
		//数据包的操作码data
		data = ntohs(*pa);
		if(data == 5)
		{
			printf("错误:%s\n",file);
			return -1;
		}
		//操作包的块编号
		block = ntohs(*(pa+1));
		//写入文件中
		if(write(fd,file,rec_size-4) < 0)
		{
			ERR_MSG("write");
			return -1;
		}
		//文件数据小于512退出,加上前面的4个字节是516
		printf("%d\n",rec_size);
		if(rec_size < 516)
		{
			printf("%s下载完成\n",FILE_NAME);
			break;
		}
		//返回的块编号
		*pa = htons(4);
		sendto(sfd,buf,4,0,(struct sockaddr*)&cin,sizeof(cin));
		
	}

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值