2022/8/10---网络编程day2

创作本文目的:记录自己的学习历程


一、TFTP协议客户端下载服务器文件

1.代码

#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 <linux/input.h>
#include <stdlib.h>

//打印错误信息的宏函数
#define ERR_MSG(msg) do{\
	fprintf(stderr,"__%d__",__LINE__);\
	perror(msg);\
}while(0)

int main(int argc, const char *argv[])
{
	//外部传参
	if(argc < 3)
	{
		fprintf(stderr,"请输入要连接的IP PORT\n");
		return -1;
	}
	//创建报式套接字
	int	sfd = socket(AF_INET,SOCK_DGRAM,0);
	if(sfd<0)
	{
		ERR_MSG("socket");
		return -1;
	}
	printf("create socket success\n");

	//绑定客户端的地址信息结构体(非必须绑定)

	//填充要连接的服务器的地址信息结构体
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(atoi(argv[2]));
	addr.sin_addr.s_addr = inet_addr(argv[1]);
	
	unsigned short count = 1;   		 //记录数据包编号
	ssize_t res=0;              		 //接收函数返回值
	char ack[4]="";          			 //ACK
	char data_buf[516]="";  			 //数据包
	char buf[128]="";       			 //读写请求
	char filename[128]=""; 				 //文件名
	char type[]="octet";   				 //模式
	char *tmp=NULL;       				 //临时接收地址				
	unsigned short *oper=NULL;           //接收操作码
	unsigned short oper_host;            //主机字节序的操作码
	unsigned short *bnum=NULL;           //接收块编号或差错码
	unsigned short bnum_host;            //主机字节序的块编号或差错码

	//1.发送下载请求
	oper=(short *)buf;
	*oper = htons(1);
	printf("请输入文件名:");
	fgets(filename,sizeof(filename),stdin);
	filename[strlen(filename)-1]=0;
	tmp = buf+2;
	strcpy(tmp,filename);
	tmp = buf+strlen(filename)+3;
	strcpy(tmp,type);
	res=sendto(sfd,(void *)buf,4+strlen(filename)+strlen(type),0,(struct sockaddr *)&addr,sizeof(addr));
	if(res<0)
	{
		ERR_MSG("send_request");
		return -1;
	}
	printf("发送下载请求成功\n");

	//创建本机接收文件
	int fd = open(filename,O_WRONLY|O_CREAT|O_TRUNC,0664);

	//接受服务器给的地址信息结构体
	struct sockaddr_in sin;
	socklen_t addrlen=sizeof(sin); 

	while(1)
	{
		//2.接收服务器数据包
		bzero(data_buf,sizeof(data_buf));
		res=recvfrom(sfd,(void *)data_buf,sizeof(data_buf),0,(struct sockaddr *)&sin,&addrlen);
		if(res<0)
		{
			ERR_MSG("recv");
			return -1;
		}
		else if(0==res)
		{
			printf("server is off-line\n");
			break;
		}
		oper_host = ntohs(*(unsigned short *)data_buf);
		if(oper_host!=3)
		{
			printf("数据包操作码不正确:%d\n",oper_host);
			bnum_host = ntohs(*((unsigned short *)data_buf+1));
			printf("差错码:%d 差错信息:%s\n",bnum_host,data_buf+4);
			continue;
		}
		bnum_host = ntohs(*((unsigned short *)data_buf+1));
		if(bnum_host!=count)
		{
			printf("数据包块编号不正确:%d\n",bnum_host);
			continue;
		}
		tmp=data_buf+4;
		if(res<512)
		{
			printf("数据传输结束\n");
			break;
		}
		res=write(fd,(void *)tmp,res-4);
	
		//3.发送ACK应答
		oper=(unsigned short *)ack;
		*oper=htons(4);
		bnum=oper+1;
		*bnum=htons(count);
		//printf("%p\t%d\n%p\t%d\n",oper,*oper,bnum,*bnum);
		res=sendto(sfd,(void *)ack,sizeof(ack),0,(struct sockaddr *)&sin,addrlen);
		if(res<0)
		{
			ERR_MSG("send_ack");
			return -1;
		}
		//printf("发送ACK成功\n");
		count++;		
	}

	//关闭套接字
	close(sfd);
	//关闭下载的文件
	close(fd);

	return 0;
}

2.运行效果

在这里插入图片描述


二、TFTP协议客户端上传本地文件

1.代码

#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 <linux/input.h>
#include <stdlib.h>

//打印错误信息的宏函数
#define ERR_MSG(msg) do{\
	fprintf(stderr,"__%d__",__LINE__);\
	perror(msg);\
}while(0)

int main(int argc, const char *argv[])
{
	//外部传参
	if(argc < 3)
	{
		fprintf(stderr,"请输入要连接的IP PORT\n");
		return -1;
	}
	//创建报式套接字
	int	sfd = socket(AF_INET,SOCK_DGRAM,0);
	if(sfd<0)
	{
		ERR_MSG("socket");
		return -1;
	}
	printf("create socket success\n");

	//绑定客户端的地址信息结构体(非必须绑定)

	//填充要连接的服务器的地址信息结构体
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(atoi(argv[2]));
	addr.sin_addr.s_addr = inet_addr(argv[1]);
	
	unsigned short count = 0;   		 //记录数据包编号
	ssize_t res=0;              		 //接收函数返回值
	char ack[128]="";          			 //ACK
	char data_buf[516]="";  			 //数据包
	char buf[128]="";       			 //读写请求
	char filename[128]=""; 				 //文件名
	char type[]="octet";   				 //模式
	char *tmp=NULL;       				 //临时接收地址				
	unsigned short *oper=NULL;           //接收操作码
	unsigned short oper_host;            //主机字节序的操作码
	unsigned short *bnum=NULL;           //接收块编号或差错码
	unsigned short bnum_host;            //主机字节序的块编号或差错码

	//1.发送上传请求
	/*
	oper=(short *)buf;
	*oper = htons(2);
		tmp = buf+2;
	strcpy(tmp,filename);
	tmp = buf+strlen(filename)+3;
	strcpy(tmp,type);
	*/
	printf("请输入文件名:");
	fgets(filename,sizeof(filename),stdin);
	filename[strlen(filename)-1]=0;
	res = sprintf(buf,"%c%c%s%c%s%c",0,2,filename,0,type,0);
	if(sendto(sfd,buf,res,0,(struct sockaddr *)&addr,sizeof(addr))<0)
	{
		ERR_MSG("send_request");
		return -1;
	}
	printf("发送下载请求成功\n");

	//打开本机上传文件
	int fd = open(filename,O_RDONLY);

	//接受服务器给的地址信息结构体
	struct sockaddr_in sin;
	socklen_t addrlen=sizeof(sin); 

	while(1)
	{
		//2.接收服务器的ACK应答
		res=recvfrom(sfd,(void *)ack,sizeof(ack),0,(struct sockaddr *)&sin,&addrlen);
		if(res<0)
		{
			ERR_MSG("send_ack");
			return -1;
		}
		//printf("接收服务器ACK成功\n");
		oper_host = ntohs(*(unsigned short *)ack);
		if(oper_host!=4)
		{
			printf("操作码不正确:%d\n",oper_host);
			bnum_host = ntohs(*((unsigned short *)ack+1));
			printf("差错码:%d 差错信息:%s\n",bnum_host,ack+4);
			continue;
		}
		bnum_host = ntohs(*((unsigned short *)ack+1));
		if(bnum_host!=count)
		{
			printf("数据包块编号不正确:%d\n",bnum_host);
			continue;
		}
		count++;


		//3.给服务器发送数据包
		bzero(data_buf,sizeof(data_buf));
		oper=(unsigned short *)data_buf;
		*oper=htons(3);
		bnum=oper+1;
		*bnum=htons(count);
		//printf("%p\t%d\n%p\t%d\n",oper,*oper,bnum,*bnum);
		tmp=data_buf+4;
		res=read(fd,tmp,512);
		if(res<0)
		{
			ERR_MSG("read");
			return -1;
		}
		res=sendto(sfd,(void *)data_buf,res+4,0,(struct sockaddr *)&sin,sizeof(sin));
		if(res<0)
		{
			ERR_MSG("recv");
			return -1;
		}
		else if(0==res)
		{
			printf("server is off-line\n");
			break;
		}
		if(res<512)
		{
			printf("数据传输结束\n");
			break;
		}
		//printf("给服务器发送数据包成功:%ld\n",res);

	}

	//关闭套接字
	close(sfd);
	//关闭上传的文件
	close(fd);

	return 0;
}

2.运行效果

在这里插入图片描述


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值