Linux--2--模拟百度网盘实现文件传输项目

Linux--2--模拟百度网盘实现文件传输项目


项目简介:用C/C++语言模拟百度网盘,实现 Windows 与 Linux 之间上传,下载,交互文件。

项目环境:Red Hat  Enterprise   Linux 6

具体实现:采用多线程编程,用创建监听套接字 socket ,用TCP协议,实现交互方式,先创建管道,然后fork产生子进程,在子进程中用exec函数进行替换命令,用管道写端dup2覆盖替换标准输出,然后父进程将管道数据读出,发送给客户端,实现下载方式,用自定义协议,服务器端给客户端发送两次接收两次,用 sendfile 函数零拷贝发送,进度条显示下载进度,断点续传,上传文件过程中实现秒传。

          本项目是实现了在不同服务器上进行文件的交互,上传以及下载。首先肯定是建立连接。本项目用的是多线程,因为是小项目,规模不大,实现百台设备间交互是可以的。创建监听套接字 socket ,用了TCP协议,因为它面向连接,更加可靠。用UDP也可以,只是比较麻烦。TCP协议和UCP协议区别就是,TCP是面向连接的、可靠的、基于字节流的传输层通信协议。UDP是无需建立连接,不可靠,面向报文。TCP只能点到点,而UDP不但支持一对一,还可以一对多,多对一,多对多的交互通信。

         实现服务器端与多个客户端连接之后,先考虑实现交互。本质上就是想在客户端也可以操作文件,比如实现ls,rm,mv等简单命令。首先我们要设定自定义协议,我设定的输入命令方式模拟Linux系统命令,比如ls就是系统的ls。都是通过调用系统命令来实现的。 

        交互具体实现过程,先用pipe创建无名管道,pipefd[0]是用于读管道,pipefd[1]是用于写管道。pipe函数返回值为0 是成功,返回-1代表失败。然后服务器端的fork产生子进程,将接收的字符串先用strtok分割字符串,在子进程中具体用execvp函数进行替换命令,用管道写端dup2覆盖替换标准输出,在这编写代码时,应该在子进程中关闭读端,在父进程中关闭写端,为保证文件读写安全。然后父进程将管道数据读出,发送给客户端。

Linux--2--模拟百度网盘实现文件传输项目

          实现下载方式,在服务器端和客户端建立连接后,给服务器端比如发送get ,代表要下载,然后服务器端中用结构体将文件的名字,文件大小,以及文件传输的位置和文件校验码存储,并发送给客户端。客户端获取到页表之后,选择想要下载的文件名,给服务器端比如发送get a.c代表想要下载a.c文件,服务端给客户端如果回复:YES#10,代表找到了a.c文件,并且文件上次已经下载过10字节了,会问是否要继续下载文件,否则重新下载。服务端给客户端如果回复ERR,就在客户端输出“此文件找不到或者没有权限下载”。客户端选择要继续下载文件,会发送:YES,选择重新下载发送:NO,服务器端收到YES之后,将按照文件传输位置开始下载。传输文件时,通过分批发送,每次会用CRC来将要发送的文件内容计算其校验码,将其添加到要传送的加密数据后面,客户端收到后,再解析包,与其校验码计算出数据是否正确,保证数据传输时没有丢失。客户端每次确认收到正确的文件时,给服务器端回复:YES,收到错误的文件时,回复:ERR。传送失败有两种方式,一种是在传输的过程中丢失数据,一种是客户端异常断网。丢失数据时,客户端校验错误,回复ERR,服务端收到后,通过指针回退将这次发送的数据重新发送。客户端断网后,服务端一直接收不到客户端的确认包,会将指针回退到刚才发送的起始位置。等到客户端重新重新建立连接的时候,就可以继续下载文件了,这样就可以实现断点续传。在下载文件的时候进度条显示下载进度,用"\r"调整光标,记得下载完成时写上退出条件,可以用文件大小比较来做退出条件。在发送文件时,用 sendfile 函数实现零拷贝发送,sendfile 函数其实为了解决客户端下载文件后又要由服务端保存,为提高效率及性能。

Linux--2--模拟百度网盘实现文件传输项目

        实现上传文件,比如客户端发送:put a.c,代表上传a.c文件,服务器端收到命令后,将磁盘剩余容量大小,发送给客户端,客户端自行判断文件大小是否满足可上传条件,然后客户端将要上传的文件名和文件大小发送给服务端,服务端确认可以上传后,发送确认包给客户端,客户端开始分批发送,每次发送数据都将校验码加载到已加密的文件后面,保证数据发送正确。出现错误情况处理方法类似下载。