c++网络编程实战——开发基于ftp协议的文件传输模块(三) 封装自己的ftp客户端

一.前言

在前面我们已经简单介绍过FTP协议的基本概念以及我们如何配置FTP服务和一些常用的ftp命令,这篇文章主要是介绍我们如何基于开源库去封装我们自己的ftp客户端。这篇文章也可以看做一篇介绍如何基于开源库去封装自己工具库的教程。

补充: 在上一篇文章中我犯了一个小错误,就是我们云服务器开放的端口协议是ipv4,但是我在ubuntu上编写ftp的配置文件vsftpd.conf上进行监听的端口所用的协议设成了IPV6,大家要记得修改一下,不然这篇文章下的部分代码会无法运行,大家也可以在看到这篇文章是使用上一篇文章的配置文件,此时我已经对它进行了改正。

二.将开源库编译成静态/动态库

首先 我们要将开源库编译成静态/动态库,项目的链接如下:
ftplib开源库
这里我们只要取用ftplib.cftplib.h即可,由于github访问的问题,后面我会将这个作为资源上传,大家按照需求自行取用。
获取了我们想要的开源库之后我们就要着手编译了,编译的makefile编写如下:

all: libftp.a libftp.solibftp.a:_ftplib.h _ftplib.cgcc -c -o libftp.a _ftplib.clibftp.so:_ftplib.h _ftplib.cgcc -fPIC -shared -o libftp.so _ftplib.cclean:rm -f libftp.a libftp.so

这要我们就可以在我们的代码中去使用这些开源库的代码了。

这里我们简单介绍一下该开源库提供的一些功能函数以及它们功能的介绍:

GLOBALREF void FtpInit(void);  //初始化函数
GLOBALREF char *FtpLastResponse(netbuf *nControl);  //获取上一次响应的函数
GLOBALREF int FtpConnect(const char *host, netbuf **nControl);  //连接函数
GLOBALREF int FtpOptions(int opt, long val, netbuf *nControl); //设置选项函数
GLOBALREF int FtpSetCallback(const FtpCallbackOptions *opt, netbuf *nControl); //设置回调函数
GLOBALREF int FtpClearCallback(netbuf *nControl); //清除回调函数
GLOBALREF int FtpLogin(const char *user, const char *pass, netbuf *nControl); //登录函数
GLOBALREF int FtpAccess(const char *path, int typ, int mode, netbuf *nControl,netbuf **nData); //访问函数
GLOBALREF int FtpRead(void *buf, int max, netbuf *nData); 
GLOBALREF int FtpWrite(const void *buf, int len, netbuf *nData);
GLOBALREF int FtpClose(netbuf *nData);
GLOBALREF int FtpSite(const char *cmd, netbuf *nControl); //site命令
GLOBALREF int FtpSysType(char *buf, int max, netbuf *nControl); //获取系统类型
GLOBALREF int FtpMkdir(const char *path, netbuf *nControl);  //创建文件夹
GLOBALREF int FtpChdir(const char *path, netbuf *nControl); //切换目录
GLOBALREF int FtpCDUp(netbuf *nControl);  //
GLOBALREF int FtpRmdir(const char *path, netbuf *nControl);  //删除文件夹
GLOBALREF int FtpPwd(char *path, int max, netbuf *nControl);  //获取当前路径
GLOBALREF int FtpNlst(const char *output, const char *path, netbuf *nControl); //列出远程服务器指定路径下的文件名
GLOBALREF int FtpDir(const char *output, const char *path, netbuf *nControl);   //列出远程服务器指定路径下的文件名和详细信息
GLOBALREF int FtpSize(const char *path, unsigned int *size, char mode, netbuf *nControl); //查询远程文件的大小
#if defined(__UINT64_MAX)
GLOBALREF int FtpSizeLong(const char *path, fsz_t *size, char mode, netbuf *nControl); 
#endif
GLOBALREF int FtpModDate(const char *path, char *dt, int max, netbuf *nControl); //获取远程文件的最后修改日期和时间。
GLOBALREF int FtpGet(const char *output, const char *path, char mode, netbuf *nControl);//从远程服务器下载文件。
GLOBALREF int FtpPut(const char *input, const char *path, char mode,netbuf *nControl); //上传文件到远程服务器
GLOBALREF int FtpRename(const char *src, const char *dst, netbuf *nControl); //在远程服务器上重命名文件或目录。
GLOBALREF int FtpDelete(const char *fnm, netbuf *nControl); //删除远程服务器上的文件。
GLOBALREF void FtpQuit(netbuf *nControl); //断开连接

下面就要开始我们基于上述开源库的客户端的封装了。

3.ftp客户端的封装

在开始对我们封装代码具体讲解之前我们先看一下整体的框架(也就是.h文件):

//_ftp.h
// 此程序是开发框架的ftp客户端工具的类的声明文件。
#ifndef __FTP_H
#define __FTP_H#include "./_public.h"
#include "_ftplib.h"namespace idc
{class cftpclient{private:netbuf *m_ftpcoon; // ftp服务的连接句柄public:unsigned int m_msize; // 文件的大小string m_mtime;       // 最后一次进行文件修改的时间// 下面是用来存放ftp登录可能出现的问题bool m_connetfailed;                                // 网络连接失败bool m_loginfailed;                                 // 登录失败(用户名/密码错误或是没有登录权限)bool m_optionfailed;                                // 设置传输模式失败cftpclient();                                       // 构造函数~cftpclient();                                      // 析构函数cftpclient(const cftpclient &) = delete;            // 禁止拷贝构造函数cftpclient &operator=(const cftpclient &) = delete; // 禁止赋值操作符void initdata();                                    // 初始化数据// 登录ftp服务器// host:ftp服务器的ip地址与端口号,如:127.0.0.1:21// username:用户名// password:密码// fmode:传输模式,默认为被动模式bool login(const string &host, const string &username, const string &password, const int fmode =FTPLIB_PASSIVE);// 断开连接bool loginout();// 获取ftp服务器上文件的时间 返回值:false-失败;true-成功,获取到的文件大小存放在m_mtime成员变量中。bool mtime(const string &filename);// 获取ftp服务器上文件的大小//  返回值:false-失败;true-成功,获取到的文件大小存放在m_size成员变量中。bool size(const string &filename);// 修改ftp服务器的工作目录// 返回值: false-失败;true-成功bool chdir(const string &dir);// 在ftp服务器上创建目录// 返回值: false-失败;true-成功bool mkdir(const string &dir);// 删除ftp服务器上的目录// 返回值: false-失败;true-成功bool rmdir(const string &dir);// 发送NLST命令列出ftp服务器目录中的子目录名和文件名。// remotedir:ftp服务器的目录名。// listfilename:用于保存从服务器返回的目录和文件名列表。// 返回值:true-成功;false-失败。// 注意:如果列出的是ftp服务器当前目录,remotedir用"","*","."都可以,但是,不规范的ftp服务器可能有差别。bool nlst(const string &remotedir, const string &listfilename);// 从ftp服务器上获取文件。// remotefilename:待获取ftp服务器上的文件名。// localfilename:保存到本地的文件名。// bcheckmtime:文件传输完成后,是否核对远程文件传输前后的时间,保证文件的完整性。// 返回值:true-成功;false-失败。// 注意:文件在传输的过程中,采用临时文件命名的方法,即在localfilename后加".tmp",在传输// 完成后才正式改为localfilename。bool get(const string &remotefilename, const string &localfilename,const bool bcheckname = true);// 向ftp服务器发送文件。// localfilename:本地待发送的文件名。// remotefilename:发送到ftp服务器上的文件名。// bchecksize:文件传输完成后,是否核对本地文件和远程文件的大小,保证文件的完整性。// 返回值:true-成功;false-失败。// 注意:文件在传输的过程中,采用临时文件命名的方法,即在remotefilename后加".tmp",在传输// 完成后才正式改为remotefilename。bool put(const string &localfilename, const string &remotefilename,const bool bcheckname = true);//删除ftp服务器上的文件//返回值:true-成功;false-失败。bool deletefile(const string &remotefilename);//重命名ftp服务器上的文件//返回值:true-成功;false-失败。bool rename(const string &oldfilename, const string &newfilename);//向ftp服务器发送site命令//command:命令的具体内容//返回值:true-成功;false-失败。bool site(const string &command);//获取服务器返回信息的最后一条char* response();};
};#endif // __FTP_H

我们可以看到主要还是怼一些我们常用的ftp命令在ftplib.c的基础上对其进行了封装,接下来我们再来看一下它的具体实现

//_ftp.cpp
#include "_ftp.h"namespace idc{cftpclient::cftpclient(){m_ftpcoon=0;m_loginfailed=0;m_optionfailed=0;m_connetfailed=0;initdata();}cftpclient::~cftpclient(){loginout();}void cftpclient::initdata(){m_msize=0;m_mtime.clear();}bool cftpclient::login(const string& host,const string& username,const string& password,const int fmode){if(m_ftpcoon!=0){FtpQuit(m_ftpcoon);m_ftpcoon=0;}m_loginfailed=m_optionfailed=m_connetfailed=0;if(FtpConnect(host.c_str(),&m_ftpcoon)==0)  {m_connetfailed=1;return false;}if(FtpLogin(username.c_str(),password.c_str(),m_ftpcoon)==0) {m_loginfailed=1;return false;}if(FtpOptions(FTPLIB_CONNMODE,long(fmode),m_ftpcoon)==0)  {m_optionfailed=1;return false;}return true;}bool cftpclient::loginout(){if(m_ftpcoon==0){return false;}FtpQuit(m_ftpcoon);m_ftpcoon=0;return true;}bool cftpclient::mtime(const string& filename){if(m_ftpcoon==0)  return false;m_mtime.clear();string mtimestr;mtimestr.resize(14);if(FtpModDate(filename.c_str(),&mtimestr[0],14,m_ftpcoon)==0) return false;//将UTC时间转换为实际时间if(addtime(mtimestr,m_mtime,0,"yyyymmddhh24miss")==0) return false;return true;}bool cftpclient::size(const string& filename){if(m_ftpcoon==0)  return false;m_msize=0;if(FtpSize(filename.c_str(),&m_msize,FTPLIB_IDLETIME,m_ftpcoon)==0) return false;return true;}bool cftpclient::chdir(const string& dirname){if (m_ftpcoon==0)  return false;if(FtpChdir(dirname.c_str(),m_ftpcoon)==0) return false;return true;}bool cftpclient::mkdir(const string& dirname){if (m_ftpcoon==0)  return false;if(FtpMkdir(dirname.c_str(),m_ftpcoon)==0) return false;return true;}bool cftpclient::rmdir(const string& dirname){if (m_ftpcoon==0)  return false;if(FtpRmdir(dirname.c_str(),m_ftpcoon)==0) return false;return true;}bool cftpclient::nlst(const string& remotedir,const string& filenamelist){if (m_ftpcoon==0)  return false;newdir(filenamelist.c_str());if(FtpNlst(filenamelist.c_str(),remotedir.c_str(),m_ftpcoon)==0) return false;return true;}bool cftpclient::get(const string &remotefilename, const string &localfilename, bool bcheckname){if (m_ftpcoon==0) return false;newdir(localfilename);string tmpfile=localfilename+".tmp";//获取远程服务器文件的时间if(mtime(remotefilename)==0) return false;//下载文件到本地的临时文件中if(FtpGet(remotefilename.c_str(),tmpfile.c_str(),FTPLIB_IMAGE,m_ftpcoon)==0) return false;//对比文件下载前和下载后的时间,如果不同,说明文件发生了改变,终止if(bcheckname){string strtime=m_mtime;if(mtime(remotefilename)==false) return false;if(strtime!=m_mtime) return false;}//更新文件信息setmtime(remotefilename,m_mtime);//将临时文件重命名为正式文件if(rename(tmpfile.c_str(),localfilename.c_str())==0) return false;size(remotefilename);return true;}bool cftpclient::put(const string &localfilename, const string &remotefilename,const bool bcheckname){if (m_ftpcoon==0) return false;newdir(remotefilename);string tmpfile=remotefilename+".tmp";string filetime1,filetime2;//获取本地文件的时间filetime1=filemtime(localfilename,filetime1); //上传文件到远程服务器的临时文件中if(FtpPut(localfilename.c_str(),tmpfile.c_str(),FTPLIB_IMAGE,m_ftpcoon)==0) return false;//对比文件上传前和上传后的时间,如果不同,说明文件发生了改变,终止if(bcheckname){if(filemtime(remotefilename,filetime2)==false) return false;if(filetime2!=filetime1) return false;}//将临时文件重命名为正式文件if(rename(tmpfile.c_str(),remotefilename.c_str())==0) return false;if(size(localfilename)==0) return false;return true;}bool cftpclient::deletefile(const string &remotefilename){if (m_ftpcoon==0) return false;if(FtpDelete(remotefilename.c_str(),m_ftpcoon)==0) return false;return true;}bool cftpclient::rename(const string &oldfilename, const string &newfilename){if (m_ftpcoon==0) return false;if(FtpRename(oldfilename.c_str(),newfilename.c_str(),m_ftpcoon)==0) return false;return true;}bool cftpclient::site(const string &command){if (m_ftpcoon==0) return false;if(FtpSite(command.c_str(),m_ftpcoon)==0) return false;return true;}char* cftpclient::response(){if(m_ftpcoon==0) return nullptr;return FtpLastResponse(m_ftpcoon);}
};

其实绝大多数的函数都不是需要过多的解释,因为主要就是对ftplib.c这个库的调用,主要要注意的是get函数与put函数,这里我们来讲一下:

-get函数

        bool cftpclient::get(const string &remotefilename, const string &localfilename, bool bcheckname){if (m_ftpcoon==0) return false;newdir(localfilename);string tmpfile=localfilename+".tmp";//获取远程服务器文件的时间if(mtime(remotefilename)==0) return false;//下载文件到本地的临时文件中if(FtpGet(remotefilename.c_str(),tmpfile.c_str(),FTPLIB_IMAGE,m_ftpcoon)==0) return false;//对比文件下载前和下载后的时间,如果不同,说明文件发生了改变,终止if(bcheckname){string strtime=m_mtime;if(mtime(remotefilename)==false) return false;if(strtime!=m_mtime) return false;}//更新文件信息setmtime(remotefilename,m_mtime);//将临时文件重命名为正式文件if(rename(tmpfile.c_str(),localfilename.c_str())==0) return false;size(remotefilename);return true;}

get函数是从ftp服务器中下载文件,这里我们的实现思路是:

  1. 检查是否连接服务器
  2. 在本地创建文件
  3. 创建临时文件接收文件
  4. 检查文件下载是否有误
  5. 将临时文件改为正式文件

put函数是从ftp服务器中下载文件,这里我们的实现思路是:

  1. 检查是否连接服务器
  2. 在服务器创建文件
  3. 创建临时文件接收文件
  4. 检查文件下载是否有误
  5. 将临时文件改为正式文件

拓展

在什么的文件中有一些函数是我自己封装的,这里就不一一展示,我和大家大概介绍一下它们的功能,大家可以尝试自己去实现一下:

  • addtime:将电脑获取的UTC时间改成指定格式的时间
  • newdir:创建指定文件/文件夹
  • setmtime:谁知文件的修改信息
  • filemtime:获取文件的最后一次修改时间

最后我还写了一个简单的测试文件,大家也可以试试或者自己写一个测试样例去试试:

#include "./_ftp.h"
using namespace idc;int main(int argc,char *argv[])
{cftpclient ftp;if(ftp.login(argv[1],argv[2],argv[3])==false){perror("ftp.login() failed.");return -1;}cout<<"ftp.login() success."<<endl;if(ftp.nlst("/public/","/tmp/list/tmp.list")==false){perror("ftp.dir() failed.");return -1;}cout<<"ftp.nlst() success."<<endl;// 在ftp服务器上创建/home/wucz/tmp,注意,如果目录已存在,会返回失败。if (ftp.mkdir("/home")==false) { printf("ftp.mkdir() failed.\n"); return -1; }// 把ftp服务器上的工作目录切换到/home/wucz/tmpif (ftp.chdir("/home")==false) { printf("ftp.chdir() failed.\n"); return -1; }return 0;
}

结语

经过上面的步骤我们就基于开源库实现了一个我们自己的ftp客户端,这篇文章一方面是写如何封装ftp客户端,另外一方面也是想介绍如何基于开源库去封装自己工具库,希望大家可以有所收获,下篇见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/387426.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中间件安全:Nginx 解析漏洞测试.

中间件安全&#xff1a;Nginx 解析漏洞测试. Nginx 是一个高性能的 HTTP和 反向代理服务器&#xff0c;Nginx 解析漏洞是一个由于配置不当导致的安全问题&#xff0c;它不依赖于Nginx或PHP的特定版本&#xff0c;而是由于用户配置错误造成的。这个漏洞允许攻击者上传看似无害的…

git的配置使用

第三周 Tursday 早 git日志的安装使用 [rootweb ~]# yum -y install git.x86_64 //安装软件包 [rootweb ~]# rpm -ql git //查看git的包 ​ [rootweb ~]# mkdir /yy000 //创建新目录 [rootweb ~]# cd /yy000/ [rootweb yy000]# git init //将当前目录做为仓库…

ubuntu 查找文件find

find -name xxx 查找当前路径下名字为xxx的文件 find . -name xxx 查找当前路径下名字为 train_logs的文件 find . -name train_logs 具体说明 【Ubuntu】find命令_ubuntu find命令-CSDN博客 其中&#xff0c;路径 指定要搜索的目录路径&#xff0c;而 表达式 用于指定匹配条…

PHP进阶-CentOS7部署LNMP服务架构的项目

在开发和部署Web应用时&#xff0c;LNMP&#xff08;Linux、Nginx、MySQL、PHP&#xff09;的组合是非常常见的。这篇博客将介绍如何通过一个简单的脚本&#xff0c;在CentOS 7上部署LNMP&#xff0c;并将PHP项目自动部署到服务器上。这不仅可以节省大量的时间&#xff0c;还能…

Wi-Fi、WLAN、Bluetooth、zigbee、蜂窝网络、4g5g、MQTT

为什么打开手机的WiFi连接&#xff0c;显示的是WLAN&#xff1f; 分清Wi-Fi、WLAN、Bluetooth、zigbee、蜂窝网络、4g5g、MQTT这些概念. 一、WLAN、WIFI、WAPI WLAN是利用无线通信技术在局部区域内构建的网络&#xff0c;家庭/办公室里的网络就是一个WLAN&#xff0c;WLAN是一…

【城市数据集】世界城市数据库和访问门户工具WUDAPT

世界城市数据库和访问门户工具WUDAPT WUDAPTLCZ分类具体步骤参考 在 城市气候研究中&#xff0c;用于描述城市特征的数据集一般采用基于类别的传统方法&#xff0c;将城市地区分为数量有限的类型&#xff0c;从而导致精确度下降。越来越多的新数据集以亚米微尺分辨率描述城市的…

SolidEdge二次开发(C#)-环境配置

文章目录 1、前言2、环境配置2.1 安装Solidworks20242.2 安装VS20222.3 查看Com组件2.3.1 在VS2022中创建一个wpf工程项目2.3.2 添加com组件 1、前言 SolidEdge是Siemens PLM Software公司旗下的三维CAD软件&#xff0c;采用Siemens PLM Software公司自己拥有专利的Parasolid作…

JAVA零基础学习3(Scanner类,字符串,StringBuilder,StringJoinder,ArrayList成员方法)

JAVA零基础学习&#xff13; Scanner类输入示例代码代码解释完整代码1. 读取字符串2. 读取整数3. 读取浮点数4. 读取布尔值5. 读取单个单词6. 读取长整型数7. 读取短整型数8. 读取字节数注意事项总结 API 字符串解释示例解释解决方法示例&#xff1a;使用 StringBuilder String…

Java代码基础算法练习-求一个3×3矩阵对角线元素之和-2024.07.27

任务描述&#xff1a; 求一个33矩阵对角线元素之和&#xff0c;包括主对角线、副对角线元素和 &#xff08;提示&#xff1a;主对角线&#xff1a; ij,副对角线&#xff1a;ij2&#xff09;。 解决思路&#xff1a; 定义 3*3 的二维数组&#xff0c;再输入9个数字&#xff0c…

【面向就业的Linux基础】从入门到熟练,探索Linux的秘密(十四)-租云服务器及配环境、docker基本命令

主要介绍了租云服务器和docker配置、基本命令&#xff01;&#xff01;&#xff01; 文章目录 前言 一、云平台 二、租云服务器及安装docker 1.阿里云 2.安装docker 三、docker命令 将当前用户添加到docker用户组 镜像&#xff08;images&#xff09; 容器(container) 四、实战…

linux编写shell脚本字段部署redis6.x版本,docker使用shell脚本一键自动部署redis

1.先创建部署脚本 touch redis.sh2.粘贴部署脚本内容到redis.sh echo "在线安装redis开始...." docker pull redis:6.2.1 sudo mkdir -p /home/admin/redis/{data,conf} sudo touch /home/admin/redis/conf/redis.conf echo " #注释掉这部分&#xff0c;这是限…

一文总结代理:代理模式、代理服务器

概述 代理在计算机编程领域&#xff0c;是一个很通用的概念&#xff0c;包括&#xff1a;代理设计模式&#xff0c;代理服务器等。 代理类持有具体实现类的实例&#xff0c;将在代理类上的操作转化为实例上方法的调用。为某个对象提供一个代理&#xff0c;以控制对这个对象的…

基于FPGA的数字信号处理(20)--半加器和全减器

1、前言 既然有半加器和全加器&#xff0c;那自然也有半减器和全减器了。尽管在电路中减法的实现基本都是 补码 加法 的形式&#xff0c;但是正所谓技多不压身&#xff0c;了解一下半减器和全减器还是有一定作用的&#xff0c;至少能扩宽知识面嘛。 2、半减器 最简单的减法器叫…

RESNET

ResNet 文章目录 ResNet主要内容开发背景解决两个问题&#xff1a;1. 梯度消失和梯度爆炸2. 退化问题: 解决方法1. BN&#xff08;Batch Normalization&#xff09;层2. 残差块 Pytorch实现BasicBlockBottleNeckResNet 主要内容 开发背景 残差神经网络(ResNet)是由微软研究院…

LLM大模型:十大人工智能大模型技术介绍

十大人工智能大模型技术的简介&#xff1a; 深度学习模型 深度学习是人工智能领域中一种重要的机器学习技术&#xff0c;通过构建深度神经网络来模拟人脑的认知过程。深度学习模型能够自动提取数据的特征&#xff0c;并在海量数据中进行学习和优化&#xff0c;从而在语音识别…

搭建规范化的vue2项目

项目包含的库 Vue2VuexRouterEslintPrettier 环境 vue&#xff1a;2.6.14 eslint&#xff1a;7.32.0 prettier&#xff1a;2.4.1 eslint-plugin-prettier&#xff1a;4.0.0 eslint-plugin-vue&#xff1a;8.0.3 vue/cli&#xff1a;5.0.8 步骤 全局安装cli工具 npm in…

CAE仿真软件怎样下载和安装?

CAE仿真软件是一类专业工程软件&#xff0c;通过数值计算和仿真技术&#xff0c;帮助工程师和设计师在计算机上模拟和分析各种工程问题&#xff0c;如结构强度、热传导、流体力学等&#xff0c;从而优化产品设计、减少试验成本&#xff0c;提高产品性能和质量。HyperWorks是常见…

快手文生图模型-Kolors快速上手

Kolors是什么 可图(Kolors)&#xff1a;用于真实感文本到图像合成的扩散模型的有效训练 可图&#xff0c;是快手开源的一个文生图模型&#xff0c;架构上使用了chatglm&#xff0c;比普通的sd模型在中文理解上要强大很多&#xff0c;以往sd模型的提示词理解能力往往只有两种 …

二进制部署k8s集群之cni网络插件flannel和calico工作原理

3、部署 CNI 网络组件 在 master01 节点上操作 上传flannel-v0.21.5.zip并解压 unzip flannel-v0.21.5.zipscp flannel*.tar 192.168.80.20:/opt/k8s/ scp flannel*.tar 192.168.80.30:/opt/k8s/ node两个节点操作 cd /opt/k8s/ docker load -i flannel.tar docker load -i …

nginx代理设置时能获取到源IP地址的方法

nginx通过http_x_forwarded_for限制来访IP示例_ngnix 根据header的x-forwarded-for限制接入-CSDN博客 名称ip客户端地址10.0.23.90nginx服务器地址110.0.202.48:18888&#xff0c;代理到10.0.204.82:8888nginx服务器地址210.0.204.82:8888&#xff0c;代理到10.0.204.82:8887后…