//按照服务器的失败次数、使用情况、成功次数排序。 static int SortCheckServer(CheckServerIP a, CheckServerIP b) { if (a.FailedCount + 3 < b.FailedCount) { return(-1); } else if (a.FailedCount > b.FailedCount + 3) { return(1); } else if (a.UseCount < b.UseCount) { return(-1); } else if (a.UseCount > b.UseCount) { return(1); } else if (a.OkCount > b.OkCount) { return(-1); } else if (a.OkCount < b.OkCount) { return(1); } else { return(0); } }
bool DownMultiFiles(DownloadData dd) { MultiFileDownData mfdd = (MultiFileDownData)dd.Data; List <DownChunkData> chunkList = new List <DownChunkData>(); List <DownChunkData> waitList = new List <DownChunkData>(); List <DownChunkData> retryList = new List <DownChunkData>(); List <CheckServerIP> serverList = new List <CheckServerIP>(); bool bHasNoYD = false; for (byte i = 0; i < mfdd.FTPIPList.Count; ++i) { CheckServerIP ssi = new CheckServerIP(i); if (mfdd.FTPIPList[i].ISP == (byte)ISPType.ISP_YD) { ssi.FailedCount = (uint)(MAX_CHUNK_COUNT * 2); } serverList.Add(ssi); if (mfdd.FTPIPList[i].ISP != (byte)ISPType.ISP_YD) { bHasNoYD = true; } } //1.划分Chunk //================================ uint tick = Utility.GetTickCount(); byte ipidx = 0; int CHUNK_SIZE2 = CHUNK_SIZE << 1; uint chunkIdx = 0; for (byte i = 0; i < mfdd.FileList.Count; ++i) { int resSize = (int)mfdd.FileList[i].ResSize; int resOffset = 0; while (resSize > 0) { DownChunkData dcd = new DownChunkData(); dcd.FileIdx = i; if (resSize >= CHUNK_SIZE2) { dcd.Length = CHUNK_SIZE; } else { dcd.Length = resSize; } dcd.ChunkIdx = chunkIdx++; dcd.Offset = resOffset; dcd.RecvSize = 0; dcd.RecvTick = 0; resOffset += dcd.Length; resSize -= dcd.Length; if (chunkList.Count < MAX_CHUNK_COUNT) { do { ipidx = (byte)((ipidx + 1) % serverList.Count); } while (bHasNoYD && mfdd.FTPIPList[ipidx].ISP == (byte)ISPType.ISP_YD); dcd.checkServer = serverList[ipidx]; dcd.checkServer.BeginUse(); if (!InitChunk(dd, dcd, mfdd.FTPIPList[ipidx])) { return(false); } dcd.RecvTick = tick; chunkList.Add(dcd); } else { waitList.Add(dcd); } } } //1.接收Chunk //================================ while (true) { tick = Utility.GetTickCount(); for (int i = 0; i < chunkList.Count;) { DownChunkData chunk = chunkList[i]; if (!DownChunk(dd, chunk, tick)) { CloseSocket(chunk); chunk.checkServer.EndUse(chunk.State != ChunkState.CHUNK_CONNECT && chunk.RecvSize != 0); if (chunk.State == ChunkState.CHUNK_RECV_DATA) { //将接收的数据coy到data CopyBuffToData(mfdd, chunk); chunk.Offset += chunk.RecvSize; chunk.Length -= chunk.RecvSize; chunk.RecvSize = 0; ++chunk.RetryCount; chunk.SendCmdData = null; } if (chunk.RetryCount >= MAX_RETRY_COUNT) { //split if ((chunk.Length > MAX_XOR_SIZE || chunk.XOR == 1) && chunk.Length > 16) { DownChunkData dcd1, dcd2; SplitChunk(ref chunkIdx, chunk, out dcd1, out dcd2); waitList.Add(dcd1); waitList.Add(dcd2); } else { chunk.RetryCount = 0; chunk.XOR = 1; chunk.SendCmdData = null; retryList.Add(chunk); } } else { retryList.Add(chunk); } Utility.ListRemoveAt(chunkList, i); continue; } else if (chunk.State == ChunkState.CHUNK_COMPLETION) { CopyBuffToData(mfdd, chunk); CloseSocket(chunk); chunk.checkServer.EndUse(true); RecvFileDataFlag cfd = mfdd.RecvFileList[chunk.FileIdx]; if (cfd.RecvSize == cfd.FileData.Length) { //完成 MultiFileOK mfo = new MultiFileOK(); mfo.Data = cfd.FileData; mfo.Drd = mfdd.FileList[chunk.FileIdx]; mfdd.CompletionList[mfdd.RecvCount] = mfo; if (++mfdd.RecvCount == mfdd.FileList.Count) { Debug.Log("所有文件完成!"); return(true); } } Utility.ListRemoveAt(chunkList, i); continue; } ++i; }//end for if (chunkList.Count < MAX_CHUNK_COUNT) { tick = Utility.GetTickCount(); DownChunkData dcd = null; if (waitList.Count > 0) { dcd = waitList[0]; waitList.RemoveAt(0); } else if (retryList.Count > 0) { dcd = retryList[0]; retryList.RemoveAt(0); } if (dcd != null) { serverList.Sort(SortCheckServer); serverList[0].BeginUse(); dcd.checkServer = serverList[0]; if (!InitChunk(dd, dcd, mfdd.FTPIPList[dcd.checkServer.ServerIdx])) { return(false); } dcd.RecvTick = Utility.GetTickCount(); chunkList.Add(dcd); } } if (mfdd.RecvCount == mfdd.FileList.Count) { break; } Thread.Sleep(1); } ; //end while return(true); }