// 功能:获取下载文件的大小 // 参数:url - 网络URL地址 // nFileSize - 输出文件的大小 // 返回值:返回true表示得到了文件的大小,URL地址有效; 返回false表示无法得到文件的信息 // 说明:这个接口是阻塞模式的,请不要在主线程调用 static public bool GetDownFileSize(string url, out int nOutFileSize, long nRandSeed = 0) { nOutFileSize = 0; CHttp http = new CHttp(nRandSeed); string szServerIP = string.Empty, szObj = string.Empty; int nPort = 80; http.ParseURL(url, ref szServerIP, ref szObj, ref nPort); string szAnswer = string.Empty; if (!http.QueryFile(ref szAnswer, szServerIP, nPort, szObj, 0, 1, false)) { http.Close(); return(false); } int nDownSize = 0, nFileSize = 0; if (!http.AnlyseFileLengthFromAnswer(szAnswer, ref nDownSize, ref nFileSize)) { http.Close(); return(false); } http.Close(); nOutFileSize = nFileSize; return(true); }
bool DownPart(CHttp http, string url, int nFileOffset, int nDownSize, int nFileSize, DownResFile resFile) { // 调用Http下载的代码 nDownSize = http.PrepareDown(url, nFileOffset, nDownSize, nDownSize == 0); if (nDownSize <= 0) { Debug.LogError("文件下载失败,url:" + url + "(" + nFileOffset + "-" + nDownSize + ")"); return(false); } // 将下载的内容提交到写线程 byte[] szTempBuf = null; int nCurDownSize = 0; int nRecTotal = 0; int nRecLen = 0; int nOffset = 0; nCurDownSize = nDownSize > 4096 ? 4096 : nDownSize; MemBlock pBlock = AllockBlock(url, nFileOffset, nCurDownSize, nFileSize); // 从内存池中取一个4K的内存片 while (nDownSize > 0 && !m_bNeedStop) { // 必要的话,在这里添加限速功能或限制接收速度的功能,以免网速太快,导致一秒内分配太多内存 //LimitSpeed(); nRecLen = http.FastReceiveMax(ref szTempBuf, ref nOffset, 4096 - nRecTotal); if (nRecLen > 0) { OnReceive(nRecLen); // 统计下载的流量 Array.Copy(szTempBuf, nOffset, pBlock.data, nRecTotal, nRecLen); nRecTotal += nRecLen; // 如果当前块接收满了 if (nRecTotal >= nCurDownSize) { pBlock.resFile = resFile; PushWrite(pBlock);// 提交写文件 nRecTotal = 0; nDownSize -= nCurDownSize; nFileOffset += nCurDownSize; nCurDownSize = nDownSize > 4096 ? 4096 : nDownSize; // 必要的话,加上限额等待 if (nCurDownSize > 0) { WaitBlock(1024 * 1024); // 检测当前内存池分配的总量,超过就挂起 pBlock = AllockBlock(url, nFileOffset, nCurDownSize, nFileSize); // 从内存池中取一个4K的内存片 } } } else { return(false); // 文件读取失败,可能是网络出问题了 } } return(true); }
// 功能:下载整个文件 // 说明:这个接口是阻塞模式的,请不要在主线程调用 static public bool DownFile(string url, out byte[] szFileData, int nDownOffset = 0, int nNeedDownSize = 0, long nRandSeed = 0, LPOnReceiveDownFile lpReceiveFunc = null) { szFileData = null; CHttp http = new CHttp(nRandSeed); string szServerIP = string.Empty, szObj = string.Empty; int nPort = 80; http.ParseURL(url, ref szServerIP, ref szObj, ref nPort); string szAnswer = string.Empty; if (!http.QueryFile(ref szAnswer, szServerIP, nPort, szObj, nDownOffset, nNeedDownSize, nNeedDownSize <= 0)) { http.Close(); return(false); } int nDownSize = 0, nFileSize = 0; if (!http.AnlyseFileLengthFromAnswer(szAnswer, ref nDownSize, ref nFileSize)) { http.Close(); return(false); } nDownSize = nFileSize; byte[] szTempBuf = null; szFileData = new byte[nFileSize]; int nRecTotal = 0; int nRecLen = 0; int nOffset = 0; while (nRecTotal < nDownSize) { nRecLen = http.FastReceiveMax(ref szTempBuf, ref nOffset); // 写入文件吧 if (nRecLen > 0) { if (lpReceiveFunc != null) { lpReceiveFunc(nRecLen); } Array.Copy(szTempBuf, nOffset, szFileData, nRecTotal, nRecLen); nRecTotal += nRecLen; } else { break; } } http.Close(); return(nRecTotal == nDownSize); }
static void Main(String[] args) { var h = new CHttp(4, DownloadChangedCallback, DownloadCompletedCallback); //h.Push(new SInObj("http://madplanet-patch.s3.ca-central-1.amazonaws.com", "/ServerInfo.txt")); h.Push(new SInObj("http://madplanet-patch.s3.ca-central-1.amazonaws.com", "/data/test2.msi")); while (true) { h.Proc(); Thread.Sleep(1); } }
public CClient( string FileName_, string ServerName_, bool VersionPath_, string DataPath_, TLinkFunc LinkFunc_, TLinkFailFunc LinkFailFunc_, TUnLinkFunc UnLinkFunc_, TDownloadChangedFunc DownloadChangedFunc_, TDownloadCompletedFunc DownloadCompletedFunc_) : base(FileName_, DataPath_) { _Http = new CHttp(1, _DownloadChanged, _DownloadCompleted); _ServerName = ServerName_; _VersionPath = VersionPath_; _LinkFunc = LinkFunc_; _DownloadChangedFunc = DownloadChangedFunc_; _DownloadCompletedFunc = DownloadCompletedFunc_; _NetB = new balance.CClient(_LinkS, LinkFailFunc_, UnLinkFunc_, _RecvS); }
void DownThread() { DownResInfo resInfo = null; CHttp http = new CHttp(); while (!m_bNeedStop) { if (PopDownFileInfo(out resInfo)) { DownFile(http, resInfo.url, resInfo.nFileSize, resInfo.nDownSize); } else { break; } } http.Close(); // 线程退出,线程数减一 System.Threading.Interlocked.Decrement(ref m_nDownThreadNumb); }
void DownFile(CHttp http, string url, int nFileSize, int nLastDownSize) { // 如果文件比较小的话,可以不分片下载,真正下载整个文件 if (nFileSize == 0) { CHttpDown.GetDownFileSize(url, out nFileSize); } DownResFile resInfo = new DownResFile(); resInfo.url = url; resInfo.nFileSize = 0; if (0 == nFileSize) { // 无法获取文件大小信息,整个下载吧 bool bSuc = DownPart(http, url, 0, 0, nFileSize, resInfo); NotifyDownEvent(url, bSuc, resInfo); return; } int nPageSize = 1024 * 300; // 分片的大小,应小于你的最大限制下载速度, 这里默认选用300K,读者自己根据项目修改 int nFileOffset = nLastDownSize; // 从上一次下载的位置接着下载 int nDownSize = 0; for (; nFileOffset < nFileSize; nFileOffset += nPageSize) { // 先限速 LimitSpeed(); // 开始分片下载 nDownSize = nFileOffset + nPageSize < nFileSize ? nPageSize : (nFileSize - nFileOffset); if (!DownPart(http, url, nFileOffset, nDownSize, nFileSize, resInfo)) { NotifyDownEvent(url, false, resInfo); return; } } NotifyDownEvent(url, true, resInfo); }
// 功能:下载文件,并将下载的文件保存到本地 // 参数:url - 网络URL的地址 // szLocalPathName - 本地保存地址 // 说明:这个接口是阻塞模式的,请不要在主线程调用 static public bool DownFile(string url, string szLocalPathName, int nNeedDownOffset, int nNeedDownSize, long nRandSeed = 0, LPOnReceiveDownFile lpReceiveFunc = null) { CHttp http = new CHttp(nRandSeed); string szServerIP = string.Empty, szObj = string.Empty; int nPort = 80; http.ParseURL(url, ref szServerIP, ref szObj, ref nPort); string szAnswer = string.Empty; if (!http.QueryFile(ref szAnswer, szServerIP, nPort, szObj, nNeedDownOffset, nNeedDownSize, nNeedDownSize <= 0)) { http.Close(); return(false); } int nDownSize = 0, nFileSize = 0; if (!http.AnlyseFileLengthFromAnswer(szAnswer, ref nDownSize, ref nFileSize)) { http.Close(); return(false); } if (nNeedDownSize <= 0) { nDownSize = nFileSize; // 这是全部下载 } // 打开本地文件 if (File.Exists(szLocalPathName)) { File.Delete(szLocalPathName); } FileStream pFile = new FileStream(szLocalPathName, FileMode.CreateNew, FileAccess.Write); // 开始下载吧 byte[] szTempBuf = null; int nRecTotal = 0; int nRecLen = 0; int nOffset = 0; while (nRecTotal < nDownSize) { nRecLen = http.FastReceiveMax(ref szTempBuf, ref nOffset); // 写入文件吧 if (nRecLen > 0) { if (lpReceiveFunc != null) { lpReceiveFunc(nRecLen); } nRecTotal += nRecLen; pFile.Write(szTempBuf, nOffset, nRecLen); } else { break; } } http.Close(); pFile.Close(); return(nRecTotal == nDownSize); }
static bool GetInetURL(string pcsURL, ref string szOutURL) { // 提取服务器的网址 string szURL = pcsURL; if (szURL.IndexOf("http://", 0) != 0) { szURL = "http://" + szURL; } string szSerIP = GetMiddle(szURL, "http://", "/"); string szObj = string.Empty; int nIndex = szURL.IndexOf('/', 6 + szSerIP.Length); if (nIndex != -1) { szObj = szURL.Substring(nIndex); // 必须有'/' } else { return(false); } int nServerPort = 80; nIndex = szSerIP.IndexOf(':', 0); if (nIndex != -1) { nServerPort = DistillNumb(szSerIP, nIndex + 1); szSerIP = szSerIP.Substring(0, nIndex); } // 连接服务器 CHttp tcpURL = new CHttp(); if (!tcpURL.ClientOpen(szSerIP, nServerPort)) { return(false); // 无法连接服务器 } // 格式化消息头 StringBuilder szBuilder = new StringBuilder(512); ///第1行:方法,请求的路径,版本 szBuilder.AppendFormat("GET {0} HTTP/1.1\r\n", szObj); ///第2行:主机 szBuilder.AppendFormat("Host:{0}\r\n", szSerIP); ///第3行: 引用网址 //szMsg.AppendFormat( "Referer:%s\r\n", szObj ); ///第4行:接收的数据类型 szBuilder.Append("Accept:*/*\r\n"); ///第5行:浏览器类型 szBuilder.Append("User-Agent:Mozilla/6.0 (compatible; MSIE 6.00; Android)\r\n"); ///第6行:连接设置,保持 //szMsg.AppendFormat( "Connection:Keep-Alive\r\n" ); szBuilder.Append("Connection:close\r\n"); szBuilder.Append("Range: bytes=0-0\r\n"); szBuilder.Append("\r\n"); string szMsg = szBuilder.ToString(); tcpURL.SendToServer(szMsg); byte [] chBuf = new byte[1]; char [] szTotalRecBuf = new char[1024]; // 应该不会这么长吧 int nTotalRecLen = 0; int nStart = 0; while (true) { int nRecLen = tcpURL.ReceiveChar(chBuf, 1024); if (nRecLen <= 0) { break; } if (nTotalRecLen + nRecLen > szTotalRecBuf.Length) { char [] szNewBuf = new char[nTotalRecLen * 2]; Array.Copy(szTotalRecBuf, 0, szNewBuf, 0, nTotalRecLen); szTotalRecBuf = szNewBuf; } szTotalRecBuf[nTotalRecLen++] = (char)chBuf[0]; nTotalRecLen += 1; if (FindHttpMsgEndFlags(szTotalRecBuf, nTotalRecLen, ref nStart)) { break; } } tcpURL.Close(); szTotalRecBuf[nTotalRecLen] = '\0'; string szAnswer = new string(szTotalRecBuf, 0, nTotalRecLen); // 分析 szOutURL = GetMiddle(szAnswer, "Location:", "\r\n"); szOutURL = szOutURL.Trim(); tcpURL.Close(); return(szOutURL.Length > 0); }