基于socket网络编程开发网盘项目

1、需求说明

        此项目主要为了实现客户端与服务器端文件的上传与下载功能,故开发时需要完成客户端程序和服务器端程序。

2、项目开发框架及工程结构

服务器端程序整体工程结构如下 

客户端程序整体如下 

 

其中并发服务器模型(一对多)的代码框架如下

while(1){
		cli_sockfd=accept(ser_sockfd, (SA *)&cli_addr, &cli_len);
		if(cli_sockfd<0){
			perror("accept");
		}
		pthread_create(&tid, NULL, recv_mess, &cli_sockfd);
	}

无连接时accept 函数会阻塞。每当产生一个新连接便创建一个新线程并传入其对应的新套接字描述符来响应每一个客户端。

 客户端程序采用轮询的方式调用每个功能函数,每个功能实现与服务器的短连接(例如查询服务器目录信息功能在其调用结束时关闭连接)

while(1){
		printf("ftp>");
		bzero(cmd,N);
		if(fgets(cmd,N-1,stdin)==NULL){
			perror("fgets");
			return -1;
		}
		cmd[N-1]='\0';
		printf("input command is %s\n",cmd);
		if(strncmp(cmd, "help", 4)==0){
			help_cmd();
		}else if (strncmp(cmd, "quit", 4)==0){
			printf("感谢使用!再见\n");
			break;
		}else if((strncmp(cmd, "ls", 2)==0) && strlen(cmd) == 3){
			ls_cmd(addr,cmd);
		}else if(strncmp(cmd, "get", 3)==0){
			get_cmd(addr, cmd);
		}else if(strncmp(cmd, "put", 3)==0){
			put_cmd(addr, cmd);
		}else if(strncmp(cmd, "ls cli", 6)==0){
			do_cli_ls_l();
		}
		else {
			printf("command is error,please try again!\n");
		}

	}

 查询服务器文件信息功能如下(其结果等待服务器端程序返回)

void ls_cmd(struct sockaddr_in addr, char *cmd)
{
	int sockfd;
	int ret;
	//system("clear");

	sockfd=socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd<0){
		perror("socket");
		exit(1);
	}
	//int on=1;
	//setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
	ret=connect(sockfd, (SA *)&addr, sizeof(addr));
	if(ret<0){
		perror("connect");
		exit(1);
	}

	ret = write(sockfd, cmd, N);
	if(ret<0){
		perror("write");
		exit(1);
	}
	
	printf(RED "************************************\n");
	printf(    "**         服务器文件内容         **\n");
	printf(    "************************************\n" NONE);
	bzero(cmd, N);
	while(read(sockfd, cmd, N) > 0){
		printf(LIGHT BLUE "****** %s\n" NONE ,cmd);
		bzero(cmd, N);
	}
	close(sockfd);
	
}

 3、TCP通信中的应答机制确保数据的可靠性

        如下是等待服务器端程序发送是否准备就绪应答,若就绪则客户端开始接收,否则return结束。

if (write(sockfd, cmd, strlen(cmd)) < 0) { //发送命令给服务器端 put xxx
		printf("put cmd error 1\n");
		exit(1);
	}
	
	bzero(buffer, N);
	read(sockfd, buffer, N);//读取服务器端应答 "ok" ,阻塞在此
	//printf("strncmp=%d\n", strncmp(buffer, "ok", 2));
	if(!strncmp(buffer, "ok", 2) == 0){
		printf("server error\n");
		return ;
	}
	
	bzero(filename, N);
	strncpy(filename, cmd+4, strlen(cmd+4) - 1); //取出文件名 xxx,-1是去掉\n
	
	printf("filename is %s\n", filename);
	fd=open(filename, O_RDONLY); //  put filename ==> filename
	if (fd < 0) {
		perror("open");
		write(sockfd, "error\n", N);
		return;
	}
	write(sockfd, "success\n", N);  //必须发此句,防止服务端read函数阻塞导致异常!!!!
	bzero(buffer, N);
	read(sockfd, buffer, N);//读取服务器端应答 "ok"
	printf("strncmp=%d\n", strncmp(buffer, "ok",2));
	if(!strncmp(buffer, "ok",2) == 0) {
		printf("server error\n");
		return;
	}

当传输的文件较大时,或服务器端与客户端程序运行环境存在差异时方能体现这种应答机制的重要性。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值