为什么服务器上的FTP上传速度达到4M左右而HTTP的下载速度才400K左右
你的服务器,在执行上传和下载的时候,还得看对方服务器的网络情况。比如,你上传和下载的目标服务器是10M ADSL,那就很好解释了,你这边是上传,他那边是接收数据“下载”,速度自然很快。你这边下载,他那边上传,自然就很慢。很多地方的上传和下载带宽都不“对称”,典型的就是ADSL。
很简单的测试方法:
建议你更换一个ftp server软件测试一下,filezilla-projectorg 开源免费的 filezilla server官网,如果安装之后,还是一样的效果,说明服务器的系统设置问题,可能真有限制。
如果改善了,说明你的server-U设置还是有问题。
-------
不管怎样,你确认server-u设置没有问题,你就需要拿另外一个证明他没有问题(而是其他的问题),如果另外一个确实是好的,你怎么能够还坚持server-U设置没有问题呢?
反过来说,用filezilla设置后上传正常,难道可以认为server-u还是没有问题?
TP连接超时,上传速度降为0 的Serv-u设置问题
1本地服务器→设置→常规→禁用反超时调度(去掉√)
2本地服务器→设置→高级→适应超时(打√)
3本地服务器→域→用户名→常规→会话超时(设置为空)
4本地服务器→域→用户名→上传/下载率→启用上传/下载比率(去掉√)
5本地服务器→域→用户名→配额→启用磁盘配额(去掉√,如需设置上传大小,可启用并设置合适的值)
以上方法适合因Serv-u设置而导致的FTP连接超时、上传限制、上传速度降为0问题。
在这里需要说明的是,该方式是通过其他代码进行改进的。 首先我们需要定义一个委托,用来实现传输过程中传递文件的总数,已完成的字节数和速度,方便客户端界面上调用。 public delegate void TransferProcess(long total,long finished,double speed); 调用代码就不举例了 接下来我们建立一个FTPClient类,该类基于socket和FTP协议实现了连接FTP服务,建立目录,上传文件,下载文件等主要方法。结构如下: 需要注意的是,我们需要定一个事件event TransferProcess OnTransferProcess;该事件在实例化FTPClient之后需要调用,这个事件对实现进度条和速率是非常重要的。为了实现速率我们还需要定义个公开的成员startTime(开始时间)。我们现在主要是看一下如何上传的。 /// /// 上传一个文件 /// /// 本地文件名 public void Put(string strFileName) { //连接服务器 if (!bConnected) { Connect(); } UpdateStatus = true; //建立socket连接 Socket socketData = CreateDataSocket(); //向FTP服务器发生存储命令 SendCommand("STOR " + PathGetFileName(strFileName)); //如何服务器返回的信息不是我们所需要的,就抛出异常 if (!(iReplyCode == 125 || iReplyCode == 150)) { throw new IOException(strReplySubstring(4)); } //建立本地文件的数据流 FileStream input = new FileStream(strFileName, FileModeOpen); int iBytes = 0; long total = inputLength;//该成员主要记录文件的总字节数,注意这里使用长整型,是为了突破只能传输2G左右的文件的限制 long finished = 0;//该成员主要记录已经传输完成的字节数,注意这里使用长整型,是为了突破只能传输2G左右的文件的限制 double speed = 0;//记录传输的速率 while ((iBytes = inputRead(buffer, 0, bufferLength)) > 0)//循环从本地数据流中读取数据到缓冲区 { //ConsoleWriteLine(startTimeToString()); socketDataSend(buffer, iBytes, 0);//将缓冲区的数据发送到FTP服务器 DateTime endTime = DateTimeNow;//每次发送数据的结束时间 TimeSpan ts = endTime - startTime;//计算每次发送数据的时间间隔 finished += iBytes;//计算完成的字节数 ConsoleWriteLine(tsMilliseconds); //计算速率,注意finished是字节,所以需要换算冲K字节 if (tsMilliseconds > 0) { speed = (double)(finished / tsTotalMilliseconds); speed = MathRound(speed 1000 / 1024, 2); } //这里是必不可少的,否则你无法实现进度条 //如果传输进度事件被实例化,而且从本地数据流中读取数据不是空的并完成的字节数也不为空的话,则实现委托 if (OnTransferProcess != null&&iBytes>0&&finished>0) { OnTransferProcess(total, finished,speed); } } UpdateStatus = false; finished = 0; inputClose();//当传输完成之后需要关闭数据流,以便下次访问 if (socketDataConnected) { socketDataClose();//关闭当前的socket } if (!(iReplyCode == 226 || iReplyCode == 250)) { ReadReply(); if (!(iReplyCode == 226 || iReplyCode == 250)) { UpdateStatus = false; throw new IOException(strReplySubstring(4)); } } } 上面代码中注释写得比较详细,这里就不再一一讲解了,关于下载中实现进度条和速率的问题可以参考以上代码进行修改 完整的代码如下: using System; using Systemnet; using SystemIO; using SystemText; using SystemnetSockets; namespace MMSEncoder { public delegate void TransferProcess(long total,long finished,double speed); /// /// FTP Client /// public class FTPClient { public event TransferProcess OnTransferProcess; public bool UpdateStatus = true; public DateTime startTime; private bool IsAbortConnect = false; #region 构造函数 /// /// 缺省构造函数 /// public FTPClient() { strRemoteHost = ""; strRemotePath = ""; strRemoteUser = ""; strRemotePass = ""; strRemotePort = 21; bConnected = false; } /// /// 构造函数 /// /// FTP服务器IP地址 /// 当前服务器目录 /// 登录用户账号 /// 登录用户密码 /// FTP服务器端口 public FTPClient(string remoteHost, string remotePath, string remoteUser, string remotePass, int remotePort) { strRemoteHost = remoteHost; strRemotePath = remotePath; strRemoteUser = remoteUser; strRemotePass = remotePass; strRemotePort = remotePort; Connect(); } #endregion #region 登陆字段、属性 /// /// FTP服务器IP地址 /// private string strRemoteHost; public string RemoteHost { get { return strRemoteHost; } set { strRemoteHost = value; } } /// /// FTP服务器端口 /// private int strRemotePort; public int RemotePort { get { return strRemotePort; } set { strRemotePort = value; } } /// /// 当前服务器目录 /// private string strRemotePath; public string RemotePath { get { return strRemotePath; } set { strRemotePath = value; } } /// /// 登录用户账号 /// private string strRemoteUser; public string RemoteUser { set { strRemoteUser = value; } } /// /// 用户登录密码 /// private string strRemotePass; public string RemotePass { set { strRemotePass = value; } } /// /// 是否登录 /// private Boolean bConnected; public bool Connected { get { return bConnected; } } #endregion #region 链接 /// /// 建立连接 /// public void Connect() { //if (IsAbortConnect) throw new IOException("用户强制终止了FTP"); socketControl = new Socket(AddressFamilyInterNetwork, SocketTypeStream, ProtocolTypeTcp); IPEndPoint ep = new IPEndPoint(IPAddressParse(RemoteHost), strRemotePort); // 链接 try { socketControlConnect(ep); } catch (Exception) { throw new IOException("无法连接到远程服务器!"); } // 获取应答码 ReadReply(); if (iReplyCode != 220) { DisConnect(); throw new IOException(strReplySubstring(4)); } // 登陆 SendCommand("USER " + strRemoteUser); if (!(iReplyCode == 331 || iReplyCode == 230)) { CloseSocketConnect();//关闭连接 throw new IOException(strReplySubstring(4)); } if (iReplyCode != 230) { SendCommand("PASS " + strRemotePass); if (!(iReplyCode == 230 || iReplyCode == 202)) { CloseSocketConnect();//关闭连接 throw new IOException(strReplySubstring(4)); } } bConnected = true; // 切换到初始目录 if (!stringIsNullOrEmpty(strRemotePath)) { ChDir(strRemotePath); } } /// /// 关闭连接 /// public void DisConnect() { if (socketControl != null) { SendCommand("QUIT"); } CloseSocketConnect(); } public void AbortConnect() { if (socketControl != null) { SendCommand("ABOR"); } IsAbortConnect = true; //CloseSocketConnect(); } #endregion #region 传输模式 /// /// 传输模式:二进制类型、ASCII类型 /// public enum TransferType { Binary, ASCII }; /// /// 设置传输模式 /// /// 传输模式 public void SetTransferType(TransferType ttType) { if (ttType == TransferTypeBinary) { SendCommand("TYPE I");//binary类型传输 } else { SendCommand("TYPE A");//ASCII类型传输 } if (iReplyCode != 200) { throw new IOException(strReplySubstring(4)); } else { trType = ttType; } } /// /// 获得传输模式 /// /// 传输模式 public TransferType GetTransferType() { return trType; } #endregion #region 文件操作 /// /// 获得文件列表 /// /// 文件名的匹配字符串 /// public string[] Dir(string strMask) { // 建立链接 if (!bConnected) { Connect(); } //建立进行数据连接的socket Socket socketData = CreateDataSocket(); //传送命令 SendCommand("NLST " + strMask); //分析应答代码 if (!(iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226)) { throw new IOException(strReplySubstring(4)); } //获得结果 strMsg = ""; while (true) { int iBytes = socketDataReceive(buffer, bufferLength, 0); strMsg += GB2312GetString(buffer, 0, iBytes); if (iBytes < bufferLength) { break; } } char[] seperator = { '
' }; string[] strsFileList = strMsgSplit(seperator); socketDataClose();//数据socket关闭时也会有返回码 if (iReplyCode != 226) { ReadReply(); if (iReplyCode != 226) { throw new IOException(strReplySubstring(4)); } } return strsFileList; } /// /// 获取文件大小 /// /// 文件名 /// 文件大小 public long GetFileSize(string strFileName) { if (!bConnected) { Connect(); } SendCommand("SIZE " + PathGetFileName(strFileName)); long lSize = 0; if (iReplyCode == 213) { lSize = Int64Parse(strReplySubstring(4)); } else { throw new IOException(strReplySubstring(4)); } return lSize; } /// /// 删除 /// /// 待删除文件名 public void Delete(string strFileName) { if (!bConnected) { Connect(); } SendCommand("DELE " + strFileName); if (iReplyCode != 250) { throw new IOException(strReplySubstring(4)); } } /// /// 重命名(如果新文件名与已有文件重名,将覆盖已有文件) /// /// 旧文件名 /// 新文件名 public void Rename(string strOldFileName, string strNewFileName) { if (!bConnected) { Connect(); } SendCommand("RNFR " + strOldFileName); if (iReplyCode != 350) { throw new IOException(strReplySubstring(4)); } // 如果新文件名与原有文件重名,将覆盖原有文件 SendCommand("RNTO " + strNewFileName); if (iReplyCode != 250) { throw new IOException(strReplySubstring(4)); } } #endregion #region 上传和下载 /// /// 下载一批文件 /// /// 文件名的匹配字符串 /// 本地目录(不得以\结束) public void Get(string strFileNameMask, string strFolder) { if (!bConnected) { Connect(); } string[] strFiles = Dir(strFileNameMask); foreach (string strFile in strFiles) { if (!strFileEquals(""))//一般来说strFiles的最后一个元素可能是空字符串 { if (strFileLastIndexOf("") > -1) { Get(strFileReplace("\r", ""), strFolder, strFileReplace("\r", "")); } } } } /// /// 下载一个文件 /// /// 要下载的文件名 /// 本地目录(不得以\结束) /// 保存在本地时的文件名 public void Get(string strRemoteFileName, string strFolder, string strLocalFileName) { if (!bConnected) { Connect(); } SetTransferType(TransferTypeBinary); if (strLocalFileNameEquals("")) { strLocalFileName = strRemoteFileName; } if (!FileExists(strLocalFileName)) { Stream st = FileCreate(strLocalFileName); stClose(); } FileStream output = new FileStream(strFolder + "\\" + strLocalFileName, FileModeCreate); Socket socketData = CreateDataSocket(); SendCommand("RETR " + strRemoteFileName); if (!(iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226 || iReplyCode == 250)) { throw new IOException(strReplySubstring(4)); } while (true) { int iBytes = socketDataReceive(buffer, bufferLength, 0); outputWrite(buffer, 0, iBytes); if (iBytes <= 0) { break; } } outputClose(); if (socketDataConnected) { socketDataClose(); } if (!(iReplyCode == 226 || iReplyCode == 250)) { ReadReply(); if (!(iReplyCode == 226 || iReplyCode == 250)) { throw new IOException(strReplySubstring(4)); } } } /// /// 上传一批文件 /// /// 本地目录(不得以\结束) /// 文件名匹配字符(可以包含和) public void Put(string strFolder, string strFileNameMask) { string[] strFiles = DirectoryGetFiles(strFolder, strFileNameMask); foreach (string strFile in strFiles) { //strFile是完整的文件名(包含路径) Put(strFile); } } /// /// 上传一个文件 /// /// 本地文件名 public void Put(string strFileName) { if (!bConnected) { Connect(); } UpdateStatus = true; Socket socketData = CreateDataSocket(); SendCommand("STOR " + PathGetFileName(strFileName)); if (!(iReplyCode == 125 || iReplyCode == 150)) { throw new IOException(strReplySubstring(4)); } FileStream input = new FileStream(strFileName, FileModeOpen); int iBytes = 0; long total = inputLength; long finished = 0; //DateTime startTime = DateTimeNow; double speed = 0; while ((iBytes = inputRead(buffer, 0, bufferLength)) > 0) { ConsoleWriteLine(startTimeToString()); socketDataSend(buffer, iBytes, 0); DateTime endTime = DateTimeNow; TimeSpan ts = endTime - startTime; finished += iBytes; ConsoleWriteLine(tsMilliseconds); if (tsMilliseconds > 0) { speed = (double)(finished / tsTotalMilliseconds); speed = MathRound(speed 1000 / 1024, 2); } if (OnTransferProcess != null&&iBytes>0&&finished>0) { OnTransferProcess(total, finished,speed); } } UpdateStatus = false; finished = 0; inputClose(); if (socketDataConnected) { socketDataClose(); } if (!(iReplyCode == 226 || iReplyCode == 250)) { ReadReply(); if (!(iReplyCode == 226 || iReplyCode == 250)) { UpdateStatus = false; throw new IOException(strReplySubstring(4)); } } } #endregion #region 目录操作 /// /// 创建目录 /// /// 目录名 public void MkDir(string strDirName) { if (!bConnected) { Connect(); } SendCommand("MKD " + strDirName); if (iReplyCode != 257) { throw new IOException(strReplySubstring(4)); } } /// /// 删除目录 /// /// 目录名 public void RmDir(string strDirName) { if (!bConnected) { Connect(); } SendCommand("RMD " + strDirName); if (iReplyCode != 250) { throw new IOException(strReplySubstring(4)); } } /// /// 改变目录 /// /// 新的工作目录名 public void ChDir(string strDirName) { if (strDirNameEquals("") || strDirNameEquals("")) { return; } if (!bConnected) { Connect(); } SendCommand("CWD " + strDirName); if (iReplyCode != 250) { throw new IOException(strReplySubstring(4)); } thisstrRemotePath = strDirName; } #endregion #region 内部变量 /// /// 服务器返回的应答信息(包含应答码) /// private string strMsg; /// /// 服务器返回的应答信息(包含应答码) /// private string strReply; /// /// 服务器返回的应答码 /// private int iReplyCode; /// /// 进行控制连接的socket /// private Socket socketControl; /// /// 传输模式 /// private TransferType trType; /// /// 接收和发送数据的缓冲区 /// private static int BLOCK_SIZE = Int16MaxValue; Byte[] buffer = new Byte[BLOCK_SIZE]; /// /// 编码方式(为防止出现中文乱码采用 GB2312编码方式) /// Encoding GB2312 = EncodingDefault ;//EncodingGetEncoding("gb2312"); #endregion #region 内部函数 /// /// 将一行应答字符串记录在strReply和strMsg /// 应答码记录在iReplyCode /// private void ReadReply() { strMsg = ""; strReply = ReadLine(); iReplyCode = Int32Parse(strReplySubstring(0, 3)); } /// /// 建立进行数据连接的socket /// /// 数据连接socket private Socket CreateDataSocket() { SendCommand("PASV"); if (iReplyCode != 227) { throw new IOException(strReplySubstring(4)); } int index1 = strReplyIndexOf('('); int index2 = strReplyIndexOf(')'); string ipData = strReplySubstring(index1 + 1, index2 - index1 - 1); int[] parts = new int[6]; int len = ipDataLength; int partCount = 0; string buf = ""; for (int i = 0; i < len && partCount <= 6; i++) { char ch = CharParse(ipDataSubstring(i, 1)); if (CharIsDigit(ch)) buf += ch; else if (ch != ',') { throw new IOException("Malformed PASV strReply: " + strReply); } if (ch == ',' || i + 1 == len) { try { parts[partCount++] = Int32Parse(buf); buf = ""; } catch (Exception) { throw new IOException("Malformed PASV strReply: " + strReply); } } } string ipAddress = parts[0] + "" + parts[1] + "" + parts[2] + "" + parts[3]; int port = (parts[4] << 8) + parts[5]; Socket s = new Socket(AddressFamilyInterNetwork, SocketTypeStream, ProtocolTypeTcp); IPEndPoint ep = new IPEndPoint(IPAddressParse(ipAddress), port); try { sConnect(ep); } catch (Exception) { throw new IOException("无法连接服务器"); } return s; } /// /// 关闭socket连接(用于登录以前) /// private void CloseSocketConnect() { if (socketControl != null) { socketControlClose(); socketControl = null; } bConnected = false; } /// /// 读取Socket返回的所有字符串 /// /// 包含应答码的字符串行 private string ReadLine() { while (true) { int iBytes = socketControlReceive(buffer, bufferLength, 0); strMsg += GB2312GetString(buffer, 0, iBytes); if (iBytes < bufferLength) { break; } } char[] seperator = { '
' }; string[] mess = strMsgSplit(seperator); if (strMsgLength > 2) { strMsg = mess[messLength - 2]; //seperator[0]是10,换行符是由13和0组成的,分隔后10后面虽没有字符串, //但也会分配为空字符串给后面(也是最后一个)字符串数组, //所以最后一个mess是没用的空字符串 //但为什么不直接取mess[0],因为只有最后一行字符串应答码与信息之间有空格 } else { strMsg = mess[0]; } if (!strMsgSubstring(3, 1)Equals(" "))//返回字符串正确的是以应答码(如220开头,后面接一空格,再接问候字符串) { return ReadLine(); } return strMsg; } /// /// 发送命令并获取应答码和最后一行应答字符串 /// /// 命令 private void SendCommand(String strCommand) { Byte[] cmdBytes = GB2312GetBytes((strCommand + "\r
")ToCharArray()); socketControlSend(cmdBytes, cmdBytesLength, 0); ReadReply(); } #endregion } }
缓解FTP传输慢的企业网络加速专线
企业网络加速专线适用场景包括:
1、更新配置
对于企业而言,经常会有网站或者配置文件更新,面对海量的应用服务器,少则几十台,多则上千台。如果直接使用公网传输的话,势必会占用宝贵的业务带宽,使用企业网络专线进行文件传输,独享内网传输,突破公网带宽限制,轻松获得峰值速率。
2、企业办公文件共享
企业有公共的文件需要共享给多组业务使用,需要将共享文件存储在存储服务器上。企业网络专线能够加速实现企业办公文件传输共享。
当FTP工具上传文件速度太慢,我们不妨更新更优质高效的文件传输网络——企业网络专线,其具备方便快捷、安全可靠、优质网速、支持用户文件传输的全部需求。
0条评论