文件下载传输项目总结

首先网络部分我采用libevent高性能网络框架,用i/o复用epoll的高效ET模式实现高并发(LT模式下:描述符上事件就绪后,如果没有把数据处理完成,或者没有处理,下一次epoll会继续提醒应用程序,直到把数据读完。ET模式下:描述符上事件就绪后,如果没有把数据处理完成,或者没有处理,下 一次epoll不会提醒应用层序,所以要求应用程序在收到一次提醒时,必须当下将所有数据处理完成),进程间使用基于c/s架构下的TCP/IP协议通信,保证数据安全(怎么保证?Tcp流式传输、滑动窗口、拥塞控制、重传、流量控制)。这是大体的框架。

其次,我首先实现了该项目的两大核心功能文件的传输和下载,这是用tcp/ip下最基本的socket编程技术实现的。listen函数:TCP服务器使用listen函数监听新的客户连接,需要创建一个监听队列存放待处理的客户连接,默认值为5,accept函数:TCP服务器端使用accept函数从listen监听队列中接受一个连接,此前是阻塞状态。当客户端向服务器发送请求链接以后,connect函数:TCP客户端使用connect函数三次握手建立与TCP服务器端的连接,链接成功以后客户端和服务器通过两个重要的接口 send() 和 recv() 函数来实现数据的收发功能。我们也自定义通信协议进行客户端与服务器的通信过程,例如,下载文件时,客户端向服务器发送“begin”,服务器收到后便开始向客户端传输文件,服务器传输完毕后向客户端发送“ok”,客户端收到后便停止数据接收close()关闭,文件传输完毕。

  1. Sendfile()零拷贝技术

    在这个过程中我们用到的最基本的read和write函数其实是很不高效的,在其中发生了四次copy的过程:调用 read 函数,文件数据 copy 到内核缓冲区、read 函数返回,文件数据从内核缓冲区 copy 到用户缓冲区、write 函数调用,将文件数据从用户缓冲区 copy 到内核与 socket 相关的缓冲区、数据从 socket 缓冲区 copy 到相关协议引擎。所以我引入了sendfile零拷贝技术(原型:sendfile (int __out_fd, int __in_fd, off_t *offset, size_t __count) __THROW;前两个参数为文件描述符,第三个参数表示sendfile开始传输数据的偏移量。第四个参数是打算传输的字节数。为了sendfile可以使用"零拷贝“特性,网卡需要支持聚合操作,此外还应具备校验和计算能力。如果你的NIC不具备这些特性,仍可以是用sendfile来发送数据,区别是内核在传输前会将所有缓冲区的内容合并)它的过程如下:sendfile 运行流程如下:sendfile 系统调用,文件数据被 copy 至内核缓冲区;再从内核缓冲区 copy 至内核中 socket 相关的缓冲区;最后再 socket 相关的缓冲区 copy 到协议引擎。减少了内核缓冲区到 user 缓冲区,再由 user 缓冲区到 socket 相关缓冲区的文件 copy的过程,虽然不是真正意义上的零拷贝,但也减少了硬盘读取次数,提高了效率。

  2. 断点续传

    当然,在这个下载上传的过程会遇到很多问题,比如客户端在服务器下载文件时,由于网络中断或者操作失误或者服务器奔溃导致传输中断,那么客户端再次下载的时候服务器又要重新上传客户端下载的文件,就会导致重复下载使得效率、性能大打折扣,所以为了解决这个问题,引入了断点续传的功能。具体实现是,首先我们保证服务器是不会修改客端上传的文件的,因此我们对于下载时的断点续传直接将客端本地已下载的文件大小发送给服务器端,服务器端将该文件通过lseek()函数直接偏移相应的大小,开始发送数据,客端开始从文件末尾开始写入,这样就实现了下载的断点续传功能。

  3. 支持大文件传输

    还有大文件的问题,在linux上,常规的ope()系统调用最多只能打开2G的文件,若大于 2G 则 open() 会执行失败,返回 -1。我们要实现大文件的传输,首先在 open() 函数这里,我们需要使用到标志 O_LARGEFILE,另外我们使用的各种文件操作函数都需要进行修改,例如原来的 lseek() 函数应改为 lseek64() 函数,原来的 ftruncate() 清空文件的函数应改为 ftruncate64() 函数,原来的 atoi() 函数要改为 atoll() 函数,还有原来获取文件大小 int 类型变量全部都要改为 long long 类型,获取文件结构体的类型要改为 stat64,函数也应改为 stat64()。接下来我们再来谈一下大文件分片传输的原理:多个上传请求均为分片的请求,把大文件分成多个小份一次一次向服务器传递分片完成后,即 upload 完成后,需要向服务器传递一个 merge 请求,让服务器将多个分片文件合成一个文件即为分片重组的过程。

  4. 秒传

    还有一个问题:用户 A 向服务器上传了一部电影,过段时间用户 B 又向服务器上传了一部电影,随着用户规模的增大,越来越多的用户都向服务器上传这部相同的电影。所以为了达到高效,就引入了秒传的功能。

    上传到服务器的每个文件,服务器都会校验 MD5 码。如果上传的该文件 MD5 码与已经存在于服务器里的文件的 MD5 码相同的话,服务器将会判断成为重复文件,只需要复制副本保存在服务器上即可,无需重新保存,因为有过这个文件,于是很快完成上传任务,并在有人需要下载的时候将原有的该文件的下载地址放出,这样通过秒传实现了服务器的高效运作。

  5. 修改最大连接数

    一般来说系统默认的open file连接数为1024,一般如果遇到文件句柄达到上限时,会碰到"Too many open files"或者Socket/File: Can’t open so many files等错误。
    为了让服务器重启之后,配置仍然有效,需要用永久生效的配置方法进行修改。下面是方法:
    修改最大连接数:首先进入su root切换为管理员身份 然后ulimit -a看openfile查最大连接数 一般系统默认最大连接数为1024
    文件下载传输项目总结_第1张图片
    通过vi/etc/security/limits.conf命令进入在文件的最后位置进行添加:* soft nofile 65536 和* hard nofile 65536 然后shutdow -r now重启 就ok了
    文件下载传输项目总结_第2张图片那么最大能修改多少呢?
    查看系统级别的能够打开的文件句柄的数量 cat /proc/sys/fs/file-max
    在这里插入图片描述

你可能感兴趣的:(操作系统)