14.9 Socket 高效文件传输

这篇具有很好参考价值的文章主要介绍了14.9 Socket 高效文件传输。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

网络上的文件传输功能也是很有必要实现一下的,网络传输文件的过程通常分为客户端和服务器端两部分。客户端可以选择上传或下载文件,将文件分块并逐块发送到服务器,或者从服务器分块地接收文件。服务器端接收来自客户端的请求,根据请求类型执行对应的操作,并根据发送的文件名或其他标识来确定要传输的文件。

在实现文件传输之前,需要先打开要传输的文件,并获取文件的大小信息,也可以通过其他方式获取文件的信息。在客户端和服务器端都准备就绪后,可以通过套接字来发送文件数据。在传输文件的过程中,可以将文件分解为若干个数据包进行传输,以减少数据传输中的丢包或传输错误。每个数据包的长度可以根据实际情况进行选择,通常选择1024字节或更大,也可以设置成更小的值。传输文件的过程中,还需要实现一定的错误处理机制,例如检测传输过程中的超时、丢包、不完整数据等情况,并在必要时进行错误重传或协商其他解决方案。

首先无论时服务端还是客户端都需要封装两个函数,其中GetFileName()函数用于当用户传入文件的具体路径信息时自动获取到该文件的文件名,第二个函数GetFileSize()则用于传入文件路径并自动获取到该文件的字节数。

// 传入路径得到文件名
char* GetFileName(char* Path)
{
  if (strchr(Path, '\\'))
  {
    char ch = '\\';
    char* ref = strrchr(Path, ch) + 1;
    return ref;
  }
  else
  {
    char ch = '/';
    char* ref = strrchr(Path, ch) + 1;
    return ref;
  }
}

// 获取文件大小
int GetFileSize(std::string FileName)
{
  FILE* pointer = NULL;
  pointer = fopen(FileName.c_str(), "rb");
  if (pointer != NULL)
  {
    fseek(pointer, 0, SEEK_END);
    int size = ftell(pointer);
    fclose(pointer);
    return size;
  }
  return 0;
}

接着我们来看一下RecvFile()接收文件函数是如何实现的,首先第一个发送用于向服务端发出我需要下载具体的那个目录下的文件,接着服务端会返回该目录文件的长度,此时我们通过fopen()创建一个新文件,并以此循环接收该文件的长度,每次接收成功后自动的fwrite写出到文件中,当文件被接收完毕后,则通过fclose(pointer)保存并关闭文件。

// 接收文件
bool RecvFile(SOCKET ptr, char* LocalPath, char* RemoteFile)
{
  // 发送需要下载的文件路径
  send(ptr, RemoteFile, strlen(RemoteFile), 0);

  // 接收文件长度
  long long file_size = 0;
  recv(ptr, (char*)&file_size, sizeof(int), 0);
  if (file_size <= 0)
  {
    return false;
  }

  // 保存文件到指定目录下
  char *file_name = GetFileName(RemoteFile);
  char file_all_name[1024] = { 0 };

  strcat(file_all_name, LocalPath);
  strcat(file_all_name, file_name);

  std::cout << "生成保存路径: " << file_all_name << std::endl;
  FILE* pointer = fopen(file_all_name, "wb");
  char buffer[1024] = { 0 };

  if (pointer != NULL)
  {
    long long length = 0;
    long long total_length = 0;

    // 循环接收字节数据,每次接收1024字节
    while ((length = recv(ptr, buffer, 1024, 0)) > 0)
    {
      // 写出文件并判断是否写出成功
      if (fwrite(buffer, sizeof(char), length, pointer) < length)
      {
        break;
      }

      // 每次累加递增
      total_length += length;
      memset(buffer, 0, 1024);

      // 判断文件长度是否全部接收完毕
      if (total_length >= file_size)
      {
        std::cout << "文件接收完毕, 接收字节数: " << total_length << std::endl;
        fclose(pointer);
        return true;
      }
    }
    fclose(pointer);
  }
  return false;
}

对于SendFile()发送文件而言首先我们接收到客户端传来的文件路径,并通过该路径得到该文件的具体长度,第一次调用发送函数将文件的长度传递给客户端,此时打开我们所需要发送的文件,并通过循环的方式向客户端传输,当数据包传输完毕后则自动关闭文件。

// 发送指定文件
bool SendFile(SOCKET ptr)
{
  // 接收文件路径
  char file_path[1024] = { 0 };
  recv(ptr, file_path, 1024, 0);

  // 得到文件长度并发送给服务端
  long long file_size = GetFileSize(file_path);

  if (file_size <= 0)
  {
    return false;
  }
  send(ptr, (char*)&file_size, sizeof(int), 0);
  std::cout << "发送文件长度: " << file_size << std::endl;

  // 循环发送数据
  char buffer[1024] = { 0 };
  FILE* pointer = fopen(file_path, "rb");
  if (pointer != NULL)
  {
    long long length = 0;
    long long total_length = 0;

    // 循环发送数据
    while ((length = fread(buffer, sizeof(char), 1024, pointer)) > 0)
    {
      send(ptr, buffer, length, 0);
      memset(buffer, 0, 1024);
      total_length += length;
    }

    if (total_length == file_size)
    {
      return true;
    }
  }
  return false;
}

14.9.1 服务端实现

如下代码展示了如何使用Winsock进行TCP协议的文件传输。首先使用WSAStartup函数对Winsock库进行初始化。然后创建一个socket,设置IP地址、端口号等信息,并将该socket和本地服务端的地址绑定起来。接下来对该socket进行监听,等待客户端的连接请求。

当有客户端连接请求到来时,accept函数会接收请求,并创建一个新的socket与客户端进行通信。在与客户端通信的过程中,可以通过sendrecv函数进行数据的传输,实现文件的上传和下载功能。此处的代码调用RecvFile函数,该函数为自定义实现的接收文件函数,负责接收数据并将接收到的文件存储到指定的路径下。

int main(int argc, char* argv[])
{
  WSADATA wsaData;
  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    exit(1);

  // 声明并初始化一个服务端(本地)的地址结构 
  sockaddr_in server_addr;
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.S_un.S_addr = INADDR_ANY;
  server_addr.sin_port = htons(8087);

  // 创建socket 
  SOCKET m_Socket = socket(AF_INET, SOCK_STREAM, 0);
  if (SOCKET_ERROR == m_Socket)
    exit(1);

  // 绑定socket和服务端(本地)地址 
  if (SOCKET_ERROR == bind(m_Socket, (LPSOCKADDR)&server_addr, sizeof(server_addr)))
    exit(1);

  // 监听 
  if (SOCKET_ERROR == listen(m_Socket, 10))
    exit(1);

  sockaddr_in client_addr;
  int client_addr_len = sizeof(client_addr);

  SOCKET m_New_Socket = accept(m_Socket, (sockaddr*)&client_addr, &client_addr_len);

  // 接收远程d://lyshark.exe放到本地的d://11g/目录下
  bool ref = RecvFile(m_New_Socket, (char*)"d://11g/", (char*)"d://lyshark.exe");
  std::cout << "接收状态: " << ref << std::endl;

  closesocket(m_New_Socket);
  closesocket(m_Socket);

  WSACleanup();
  system("pause");
  return 0;
}

14.9.2 客户端实现

如下客户端代码实现了一个基于TCP协议的文件传输客户端。首先使用WSAStartup函数对Winsock库进行初始化。然后创建一个socket,并设置服务端的IP地址和端口号。之后通过connect函数与服务端建立连接,连接成功后调用SendFile函数进行文件传输,将指定的文件发送到服务端。文件传输完成后,关闭socket连接,清除Winsock资源。

int main(int argc, char* argv[])
{
  while (true)
  {
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
      exit(1);

    // 创建socket 
    SOCKET c_Socket = socket(AF_INET, SOCK_STREAM, 0);

    //指定服务端的地址 
    sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    server_addr.sin_port = htons(8087);

    if (SOCKET_ERROR != connect(c_Socket, (LPSOCKADDR)&server_addr, sizeof(server_addr)))
    {
      bool ref = SendFile(c_Socket);
      std::cout << "文件发送状态: " << ref << std::endl;
    }
    closesocket(c_Socket);
    WSACleanup();
    Sleep(1000);
  }
  return 0;
}

文件传输功能代码就这些,其实理解起来并不难,读者可自行编译并运行上述代码,运行后则可接收远程d://lyshark.exe文件,并放到本地的d://11g/目录下,输出效果图如下;

14.9 Socket 高效文件传输文章来源地址https://www.toymoban.com/news/detail-710783.html

到了这里,关于14.9 Socket 高效文件传输的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用OpenWRT配置SFTP远程文件传输,安全高效的文件传输方法

    本次教程我们将在OpenWRT上安装SFTP服务,并结合cpolar内网穿透,创建安全隧道映射22端口,实现在公网环境下远程OpenWRT SFTP,安全地传输文件,比如备份文件、配置文件等。 SFTP是一种安全文件传输协议,它基于SSH协议,提供了加密、认证和数据完整性保护的安全文件传输服务

    2024年02月09日
    浏览(44)
  • C/C++用socket实现简单的TCP文件传输

    进程通信的首要问题是如何唯一标识一个进程 本地可以通过进程PID来唯一标识一个进程 网络中ip可以唯一标识一台主机;“协议 + 端口”可以唯一标识主机中的进程 因此,通过三元组(ip地址,协议,端口)就可以唯一标识网络中的进程了 使用TCP/IP协议的应用程序通常采用

    2024年02月04日
    浏览(29)
  • Nginx静态资源传输优化,文件高效传输,事半功倍

    Nginx可以作为静态资源服务器,比如我们访问 192.168.110.97:80 ,熟悉的nginx欢迎界面,这其实也是nginx为我们提供的一个静态文件: index.html 。 既然是静态资源,那我们能否优化一下传输效率呢? 1)sendfile文件高效传输模式。如何开启?它的原理到底是什么呢? 2)数据量大,

    2024年02月03日
    浏览(35)
  • 如何最高效实现手机~电脑端文件传输?

    平常使用电脑办公的时候,经常会有把手机上的文件传到电脑或把电脑上的文件分发给局域网(内网)的各个伙伴的情况,通常我们会选择使用QQ或微信的文件传输功能来实现。 但是当文件比较大、比较多时,就无法发送了。再者每次通过文件助手来发送文件时,其本质会通

    2024年02月10日
    浏览(34)
  • socket套接字通信 TCP传输控制协议/IP网络协议 5.18

    B/S :浏览器和服务器 C/S :客户机和服务器 网络的层次结构和每层所使用协议的集合 网络采用分层管理的方法,将网络的功能划分为不同的模块 OSI模型: 共7种: 数据的封装与传递过程: 网络传输数据大小user data: 6~1460 网络传输中容易发生拆包和粘包,所以接收和发送的字节

    2024年02月05日
    浏览(65)
  • 跨国企业如何高效又安全的传输视频大文件?

    在视频传输需求日益增长的今天,如何高效、安全地传输视频大文件成为跨国企业面临的重要问题。传统的文件传输方式存在诸多弊端,无法满足跨国企业对于传输效率、文件安全以及合规性的需求。那么跨国企业如何在市场是找到一种文件传输工具能在安全性、稳定性和高

    2024年01月20日
    浏览(41)
  • HTTP第14讲——HTTP传输大文件的方法

    HTTP 可以传输很多种类的数据,不仅是文本,也能传输图片、音频和视频。 早期互联网上传输的基本上都是只有几 K 大小的文本和小图片,现在的情况则大有不同。网页里包含的信息实在是太多了,随随便便一个主页 HTML 就有可能上百 K,高质量的图片都以 M 论,更不要说那

    2024年02月07日
    浏览(25)
  • 快速高效的C#FTP文件传输库FluentFTP

    简介: FluentFTP是一个用于C#语言的FTP客户端库,它提供了许多方便的功能和API,使FTP文件传输变得简单易用。FluentFTP的主要目标是提供简单易用的API,并同时提供足够的灵活性以满足大多数开发人员的需求。 FluentFTP支持FTP和FTPS协议,可以通过简单的API进行连接、上传、下载

    2024年02月02日
    浏览(18)
  • FluentFTP实战:轻松操控FTP文件,创造高效传输体验

      概述: 通过FluentFTP库,轻松在.NET中实现FTP功能。支持判断、创建、删除文件夹,判断文件是否存在,实现上传、下载和删除文件。简便而强大的FTP操作,提升文件传输效率。 在.NET中,使用FluentFTP库可以方便地实现FTP的相关功能。以下是判断文件夹是否存在、文件夹的创建

    2024年02月19日
    浏览(29)
  • Xshell+Xftp:高效、安全的远程连接和文件传输工具

    Xshell和Xftp是Windows下的两款软件。 Xshell  是一个终端模拟器,支持SSH、Telnet、Rlogin、Serial等协议,可以用于远程连接Linux、Unix等服务器。 Xftp  是一个文件传输工具,支持FTP、SFTP、SCP等协议,可以用于文件传输。 两款软件可以互相配合使用,提供了一种高效、安全的远程连接

    2024年02月16日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包