TFTP协议下载实验

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define PORT 69
#define IP "192.168.122.87"
#define FINENAME "1_armcli.c"
int main(int argc, const char *argv[])
{
	//创建报式套接字
	int cfd = socket(AF_INET,SOCK_DGRAM,0);
	if(cfd < 0)
	{
		perror("socket");
		return -1;
	}
	printf("socket success...\n");

	//填充服务器地址信息结构体
	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(PORT);
	sin.sin_addr.s_addr = inet_addr(IP);



	//读写请求
	char buf[516] = "";
	//操作码
	unsigned short *p1 = (unsigned short *)buf;
	*p1 = htons(1);
	//文件名
	char *p2 = buf+2;
	strcpy(p2,FINENAME);
	//0
	char *p3 = p2+strlen(p2);
	*p3 = 0;
	//模式
	char *p4 = p3+1;
	strcpy(p4,"octet");

	//发送读写请求
	if(sendto(cfd,buf,2+strlen(p2)+1+strlen(p4)+1,0,(struct sockaddr *)&sin,sizeof(sin)) < 0)
	{
		perror("sendto");
		return -1;
	}

	ssize_t res = 0;
	socklen_t addrlen = sizeof(sin);
	unsigned short num = 1; //块编号
	int fd = -1;  //定义本地下载文件描述符

	while(1)
	{
		//接收数据包
		bzero(buf,sizeof(buf));
		res = recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr *)&sin,&addrlen);
		if(res < 0)
		{
			perror("recvfrom");
			return -1;
		}

		//判断块编号,避免数据包重复
		if(3 == ntohs(*(unsigned short *)buf))
		{
			if(htons(num) == *(unsigned short *)(buf+2))
			{
				num++;
				if(-1 == fd)
				{
					fd = open(FINENAME,O_WRONLY|O_CREAT|O_TRUNC,0664);
					if(fd < 0)
					{
						perror("open");
						break;
					}
				}
				if(write(fd,buf+4,res-4) < 0)
				{
					perror("write");
					return -1;
				}

				//回复ACK
				*(unsigned short *)buf = htons(4);
				if(sendto(cfd,buf,4,0,(struct sockaddr *)&sin,sizeof(sin)) < 0)
				{
					perror("sendto");
					return -1;
				}
				//数据包小于512,结束
				if(res - 4 < 512)
				{
					printf("download success\n");
					break;
				}
			}
		}
		else if(5 == ntohs(*(unsigned short *)buf))
		{
			printf("%s\n",buf+4);
			break;
		}
	}
	//关闭文件描述符
	close(fd);
    close(cfd);
	return 0;
}

你可能感兴趣的:(IO进程线程练习,网络编程)