2023年4月22日 星期六 网络编程作业

基于UDP客户端下载与上传

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>

#define ERR_MSG(msg) do{\
	fprintf(stderr,"line:%d",__LINE__);\
	perror(msg);\
}while(0)

#define IP "192.168.0.172"
#define PORT 69

int main(int argc, const char *argv[])
{
	//创建报式套接字
	int cfd = socket(AF_INET,SOCK_DGRAM,0);
	if(cfd < 0){
		ERR_MSG("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);

	//判断是下载还是上传
	int flag = 0;
	int a= 0;
	printf("请输入是下载还是上传(1:下载,2:上传):\n");
	scanf("%d",&a);
	if(a == 1){
		flag = 1;
	}else if(a == 2){
		flag = 0;
	}
	//下载
	if(flag == 1){
		//向这服务器发送下载请求
		char buf[516] = "";
		char filename[20] = "";
		printf("输入要下载的文件名:");
		scanf("%s",filename);
		memset(buf,0,sizeof(buf));
		int size = sprintf(buf,"%c%c%s%c%s%c",0x00,0x01,filename,0,"octet",0);
		if(sendto(cfd,buf,size,0,(struct sockaddr *)&sin,sizeof(sin)) < 0){
			ERR_MSG("sendto");
			return -1;
		}
		printf("sendto success\n");

		struct sockaddr_in ser_sin;//ser_sin表示服务器回复时的IP和随机端口
		socklen_t addrlen = sizeof(ser_sin);
		ssize_t res = 0;
		int fd = 0;
		int size_ACK = 0;
		fd = open(filename,O_RDWR|O_CREAT|O_TRUNC,0666);
		while(1){
			//接受服务器发送的数据包
			memset(buf,0,sizeof(buf));
			res = recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr *)&ser_sin,&addrlen);
			if(res < 0){
				ERR_MSG("recvfrom");
				return -1;
			}
			printf("[%s:%d]\n",inet_ntoa(ser_sin.sin_addr),ntohs(ser_sin.sin_port));

			//如果接收的是数据包
			//提取数据包的数据(buf+4),另存到文件中
			if(buf[1] == 0x03 && (res-4) >= 512){
				write(fd,buf+4,res-4);
				//给服务器回复ACK-->组ACK包,快编号与接收到的数据包的快编号一致
				size_ACK = sprintf(buf,"%c%c%c%c",0x00,0x04,buf[2],buf[3]);
				if(sendto(cfd,buf,size_ACK,0,(struct sockaddr *)&ser_sin,sizeof(ser_sin)) < 0){
					ERR_MSG("sendto");
					return -1;
				}
			}else if(buf[1] == 0x03 && (res-4) < 512){
				write(fd,buf+4,res-4);	
				printf("下载完成\n");
				break;
			}else if(buf[1] == 0x05){
				printf("%c%c\n",buf[2],buf[3]);
				printf("%s\n",buf+4);
				break;
			}

		}
	}else if(flag == 0){
		//向这服务器发送上传请求
		char buf[516] = "";
		char filename[20] = "";
		printf("1\n");
		printf("输入要上传的文件名:");
		scanf("%s",filename);
		memset(buf,0,sizeof(buf));
		int size = sprintf(buf,"%c%c%s%c%s%c",0x00,0x02,filename,0,"octet",0);
		if(sendto(cfd,buf,size,0,(struct sockaddr *)&sin,sizeof(sin)) < 0){
			ERR_MSG("sendto");
			return -1;
		}
		printf("sendto success\n");

		struct sockaddr_in ser_sin;//ser_sin表示服务器回复时的IP和随机端口
		socklen_t addrlen = sizeof(ser_sin);
		ssize_t res = 0;
		int fd = 0;
		int size_ACK = 0;		
		fd = open(filename,O_RDONLY,0666);
		char r_buf[512] = "";
		int read_res = 0;
		char buf_ACK[4] = "";
		char g = 0x01;
		while(1){
			//接受服务器回复的ACK包
			memset(buf_ACK,0,sizeof(buf_ACK));
			memset(buf,0,sizeof(buf));
			res = recvfrom(cfd,buf_ACK,sizeof(buf_ACK),0,(struct sockaddr *)&ser_sin,&addrlen);
			if(res < 0){
				ERR_MSG("recvfrom");
				return -1;
			}
			//printf("[%s:%d]\n",inet_ntoa(ser_sin.sin_addr),ntohs(ser_sin.sin_port));
			printf("%d%d%d%d\n",buf_ACK[0],buf_ACK[1],buf_ACK[2],buf_ACK[3]);
			//根据服务器回复的ACK包封装数据包
			buf_ACK[1] = 0x03;
			buf_ACK[3] = buf_ACK[3]+1;
			buf[0] = buf_ACK[0];
			buf[1] = buf_ACK[1];
			buf[2] = buf_ACK[2];
			buf[3] = buf_ACK[3];
			char *p = buf+4;
			read_res = read(fd,r_buf,sizeof(r_buf));	
			strcat(p,r_buf);
			printf("buf =%ld\n",sizeof(buf));
			if(sendto(cfd,buf,read_res+4,0,(struct sockaddr *)&ser_sin,sizeof(ser_sin)) < 0){
				ERR_MSG("sendto");
				return -1;
			}
			printf("sendto success\n");
			if(read_res < 512){
				break;
			}
		}

	}
	close(cfd);
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值