zoukankan      html  css  js  c++  java
  • 一个C#文件传输模块,支持断点续传

    最近做一个程序需要传送文件,在网上找了好久也没找到好用的方案,于是自己写了一个,与大家分享,希望大家帮忙改进,拍砖欢迎~
    文件采取分块发送,每块单独校验,能够保证文件的完整性.同时还提供磁盘缓存功能.
    经过实际测试,通过局域网(有线和WiFi)传送一个5G左右的文件取得成功.
    最大缺点是CPU占用率过高,测试中发送端(939AMD3000+)达到40%,接收端(双核T9600、939AMD3200+)分别为15%和35%左右.
    性能确实还有待改进....
    贴出部分代码,其他的放附件里:
    复制代码
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;
    namespace Takamachi660.FileTransmissionSolution
    {//Version 0.6
        #region CRC32算法
        
    /// <summary>
        
    /// CRC32快速检测算法
        
    /// 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ZZJ_4Ever/archive/2009/03/31/4038551.aspx
        
    /// 有稍作修改
        
    /// </summary>

        public static class CRC32
        
    {
            
    static UInt32[] crcTable = {   
             
    0x00x770730960xee0e612c0x990951ba0x76dc4190x706af48f0xe963a5350x9e6495a3,   
             
    0xedb88320x79dcb8a40xe0d5e91e0x97d2d9880x9b64c2b0x7eb17cbd0xe7b82d070x90bf1d91,   
             
    0x1db710640x6ab020f20xf3b971480x84be41de0x1adad47d0x6ddde4eb0xf4d4b5510x83d385c7,   
             
    0x136c98560x646ba8c00xfd62f97a0x8a65c9ec0x14015c4f0x63066cd90xfa0f3d630x8d080df5,   
             
    0x3b6e20c80x4c69105e0xd56041e40xa26771720x3c03e4d10x4b04d4470xd20d85fd0xa50ab56b,   
             
    0x35b5a8fa0x42b2986c0xdbbbc9d60xacbcf9400x32d86ce30x45df5c750xdcd60dcf0xabd13d59,   
             
    0x26d930ac0x51de003a0xc8d751800xbfd061160x21b4f4b50x56b3c4230xcfba95990xb8bda50f,   
             
    0x2802b89e0x5f0588080xc60cd9b20xb10be9240x2f6f7c870x58684c110xc1611dab0xb6662d3d,   
             
    0x76dc41900x1db71060x98d220bc0xefd5102a0x71b185890x6b6b51f0x9fbfe4a50xe8b8d433,   
             
    0x7807c9a20xf00f9340x9609a88e0xe10e98180x7f6a0dbb0x86d3d2d0x91646c970xe6635c01,   
             
    0x6b6b51f40x1c6c61620x856530d80xf262004e0x6c0695ed0x1b01a57b0x8208f4c10xf50fc457,   
             
    0x65b0d9c60x12b7e9500x8bbeb8ea0xfcb9887c0x62dd1ddf0x15da2d490x8cd37cf30xfbd44c65,   
             
    0x4db261580x3ab551ce0xa3bc00740xd4bb30e20x4adfa5410x3dd895d70xa4d1c46d0xd3d6f4fb,   
             
    0x4369e96a0x346ed9fc0xad6788460xda60b8d00x44042d730x33031de50xaa0a4c5f0xdd0d7cc9,   
             
    0x5005713c0x270241aa0xbe0b10100xc90c20860x5768b5250x206f85b30xb966d4090xce61e49f,   
             
    0x5edef90e0x29d9c9980xb0d098220xc7d7a8b40x59b33d170x2eb40d810xb7bd5c3b0xc0ba6cad,   
             
    0xedb883200x9abfb3b60x3b6e20c0x74b1d29a0xead547390x9dd277af0x4db26150x73dc1683,   
             
    0xe3630b120x94643b840xd6d6a3e0x7a6a5aa80xe40ecf0b0x9309ff9d0xa00ae270x7d079eb1,   
             
    0xf00f93440x8708a3d20x1e01f2680x6906c2fe0xf762575d0x806567cb0x196c36710x6e6b06e7,   
             
    0xfed41b760x89d32be00x10da7a5a0x67dd4acc0xf9b9df6f0x8ebeeff90x17b7be430x60b08ed5,   
             
    0xd6d6a3e80xa1d1937e0x38d8c2c40x4fdff2520xd1bb67f10xa6bc57670x3fb506dd0x48b2364b,   
             
    0xd80d2bda0xaf0a1b4c0x36034af60x41047a600xdf60efc30xa867df550x316e8eef0x4669be79,   
             
    0xcb61b38c0xbc66831a0x256fd2a00x5268e2360xcc0c77950xbb0b47030x220216b90x5505262f,   
             
    0xc5ba3bbe0xb2bd0b280x2bb45a920x5cb36a040xc2d7ffa70xb5d0cf310x2cd99e8b0x5bdeae1d,   
             
    0x9b64c2b00xec63f2260x756aa39c0x26d930a0x9c0906a90xeb0e363f0x720767850x5005713,   
             
    0x95bf4a820xe2b87a140x7bb12bae0xcb61b380x92d28e9b0xe5d5be0d0x7cdcefb70xbdbdf21,   
             
    0x86d3d2d40xf1d4e2420x68ddb3f80x1fda836e0x81be16cd0xf6b9265b0x6fb077e10x18b74777,   
             
    0x88085ae60xff0f6a700x66063bca0x11010b5c0x8f659eff0xf862ae690x616bffd30x166ccf45,   
             
    0xa00ae2780xd70dd2ee0x4e0483540x3903b3c20xa76726610xd06016f70x4969474d0x3e6e77db,   
             
    0xaed16a4a0xd9d65adc0x40df0b660x37d83bf00xa9bcae530xdebb9ec50x47b2cf7f0x30b5ffe9,   
             
    0xbdbdf21c0xcabac28a0x53b393300x24b4a3a60xbad036050xcdd706930x54de57290x23d967bf,   
             
    0xb3667a2e0xc4614ab80x5d681b020x2a6f2b940xb40bbe370xc30c8ea10x5a05df1b0x2d02ef8d,                          
                                       }
    ;
            
    public static int GetCRC32(byte[] bytes)
            
    {
                
    int iCount = bytes.Length;
                UInt32 crc 
    = 0xFFFFFFFF;
                
    for (int i = 0; i < iCount; i++)
                
    {
                    crc 
    = ((crc >> 8& 0x00FFFFFF^ crcTable[(crc ^ bytes[i]) & 0xFF];
                }

                UInt32 temp 
    = crc ^ 0xFFFFFFFF;
                
    int t = (int)temp;
                
    return (t);
            }

        }

        
    #endregion


        
    #region 一些常量和扩展方法
        
    /// <summary>
        
    /// 一些常量和扩展方法
        
    /// </summary>

        public static class Consts
        
    {
            
    /// <summary>
            
    /// 文件区块数据标头
            
    /// </summary>

            public const byte FileBlockHeader = 0;
            
    /// <summary>
            
    /// 字符串信息标头
            
    /// </summary>

            public const byte StringHeader = 1;
            
    /// <summary>
            
    /// 分块大小1MB
            
    /// </summary>

            public const int BlockSize = 1048576;
            
    /// <summary>
            
    /// 网络上传送的数据包最大大小
            
    /// </summary>

            public const int NetBlockMaxSize = BlockSize + 9;
            
    /// <summary>
            
    /// 默认磁盘缓存大小(单位:区块数)
            
    /// </summary>

            public const int DefaultIOBufferSize = 8;
            
    /// <summary>
            
    /// 空格
            
    /// </summary>

            public const string Space = " ";
            
    /// <summary>
            
    /// 空格替代符
            
    /// </summary>

            public const string SpaceReplacement = @"<SPACE>";
            
    /// <summary>
            
    /// 获取校验值
            
    /// </summary>
            
    /// <param name="bytes">输入数据</param>
            
    /// <returns>输出的校验值</returns>

            public static byte[] GetHash(this byte[] bytes)
            
    {
                
    return BitConverter.GetBytes(CRC32.GetCRC32(bytes));
            }

            
    /// <summary>
            
    /// 比较两二进制数据内容是否完全相同(用于校验值的比较)
            
    /// </summary>
            
    /// <param name="THIS">数据一</param>
            
    /// <param name="obj">数据二</param>

            public static bool BytesEqual(this byte[] THIS, byte[] obj)
            
    {
                
    if (THIS.Length != obj.Length)
                    
    return false;
                
    for (int index = 0; index < obj.Length; index++)
                
    {
                    
    if (THIS[index] != obj[index])
                        
    return false;
                }

                
    return true;
            }

            
    /// <summary>
            
    /// 将指令字符串转化为二进制数据并添加标头
            
    /// </summary>

            public static byte[] ToBytes(this string str_input)
            
    {
                
    byte[] strdata = Encoding.UTF8.GetBytes(str_input);
                
    byte[] output = new byte[1 + strdata.Length];
                output[
    0= StringHeader;
                System.Array.Copy(strdata, 
    0, output, 1, strdata.Length);
                
    return output;
            }

            
    /// <summary>
            
    /// 将二进制数据转化为指令字符串
            
    /// </summary>

            public static string ToFTString(this byte[] bytes_input)
            
    {
                
    if (bytes_input[0!= StringHeader)
                    
    throw new FormatException("Bad Header!");
                
    return Encoding.UTF8.GetString(bytes_input, 1, bytes_input.Length - 1).TrimEnd('');
            }

            
    /// <summary>
            
    /// 替换可能会对命令解析造成干扰的字符
            
    /// </summary>

            public static string DoReplace(this string str_input)
            
    {
                
    return str_input.Replace(Space, SpaceReplacement);
            }

            
    /// <summary>
            
    /// 还原被替换的字符
            
    /// </summary>

            public static string DeReplace(this string str_input)
            
    {
                
    return str_input.Replace(SpaceReplacement, Space);
            }

        }

        
    #endregion


        
    #region 一些委托
        
    public delegate void BlockFinishedEventHandler(object sender, BlockFinishedEventArgs e);
        
    public delegate void CommandReceivedEventHandler(object sender, CommandReceivedEventArgs e);
        
    public delegate void FileTransmissionErrorOccurEventHandler(object sender,FileTransmissionErrorOccurEventArgs e);
        
    public delegate void Delegate_SendBlocks(int Start, int End);
        
    public delegate void Delegate_Void_Bool(bool logic);
        
    public delegate int Delegate_Int_Int(int value);
        
    #endregion


        
    #region 文件区块类
        
    public class FileBlockException : Exception
        
    {
            
    public enum ErrorCode
            
    {
                BadHeader,
                BadIndex,
                IllegalFileBlockSize,
                ChecksumError,
            }

            
    public ErrorCode Code getset; }
            
    public FileBlockException(string message, ErrorCode ErrorCode)
                : 
    base(message)
            
    {
                Code 
    = ErrorCode;
            }

        }

        
    /// <summary>
        
    /// 文件区块类
        
    /// </summary>

        public class FileBlock : IComparable<FileBlock>
        
    {
            
    /// <summary>
            
    /// 与该区块关联的传输对象
            
    /// </summary>

            internal FileTransmission _Task;
            
    /// <summary>
            
    /// 与该区块关联的FileStream
            
    /// </summary>

            internal FileStream _FileStream;
            
    /// <summary>
            
    /// 文件数据
            
    /// </summary>

            internal byte[] _Data;
            
    /// <summary>
            
    /// 数据长度
            
    /// </summary>

            internal int _DataLength;
            
    /// <summary>
            
    /// 数据的Hash值
            
    /// </summary>

            internal byte[] _DataHash;
            
    /// <summary>
            
    /// 获取或设置该区块的序号(该区块在文件中的位置)
            
    /// </summary>

            public int Index getset; }
            
    /// <summary>
            
    /// 获取该区块的数据长度
            
    /// </summary>

            public int DataLength get return _DataLength; } }
            
    /// <summary>
            
    /// 获取该数据块的校验值
            
    /// </summary>

            public byte[] DataHash get return _DataHash; } }
            
    /// <summary>
            
    /// 构造函数
            
    /// 用于从文件读入区块
            
    /// </summary>
            
    /// <param name="fStream">输入的文件流</param>
            
    /// <param name="BlockIndex">分块位置</param>
            
    /// <param name="ReadOnCreated">是否立即从文件读取数据</param>

            public FileBlock(FileTransmission TransmissionTask, int BlockIndex, bool ReadOnCreated)
            
    {
                _Task 
    = TransmissionTask;
                _FileStream 
    = _Task.FileStream;
                Index 
    = BlockIndex;
                
    if (ReadOnCreated)
                    
    this.Read(true);
            }

            
    /// <summary>
            
    /// 构造函数
            
    /// 用于从二进制数据读入区块
            
    /// </summary>
            
    /// <param name="fStream">要保存的文件流</param>
            
    /// <param name="ReceivedData">输入的二进制数据</param>

            public FileBlock(FileTransmission TransmissionTask, byte[] ReceivedData)
            
    {
                _Task 
    = TransmissionTask;
                _FileStream 
    = _Task.FileStream;
                
    if (ReceivedData[0!= Consts.FileBlockHeader)
                    
    throw new FileBlockException("Bad Header!", FileBlockException.ErrorCode.BadHeader);
                Index 
    = BitConverter.ToInt32(ReceivedData, 1);
                _DataLength 
    = ReceivedData.Length - 9;
                
    if (_DataLength > Consts.BlockSize)
                    
    throw new FileBlockException("Illegal FileBlock Size!", FileBlockException.ErrorCode.IllegalFileBlockSize);
                _Data 
    = new byte[_DataLength];
                _DataHash 
    = new byte[4];
                System.Array.Copy(ReceivedData, 
    5, _DataHash, 04);
                System.Array.Copy(ReceivedData, 
    9, _Data, 0, _DataLength);
                
    if (!_DataHash.BytesEqual(_Data.GetHash()))
                    
    throw new FileBlockException("Error Hash!", FileBlockException.ErrorCode.ChecksumError);
            }

            
    /// <summary>
            
    /// 从文件读入
            
    /// </summary>
            
    /// <param name="CalcHashAfterRead">是否在读取后立即计算校验值</param>
            
    /// <returns>读取块的大小</returns>

            public int Read(bool CalcHashAfterRead)
            
    {
                _Data 
    = new byte[Consts.BlockSize];
                
    lock (_FileStream)
                
    {
                    _FileStream.Position 
    = (long)Index * (long)Consts.BlockSize;
                    _DataLength 
    = _FileStream.Read(_Data, 0, Consts.BlockSize);
                }

                
    if (_Data.Length != _DataLength)
                
    {
                    
    byte[] old = _Data;
                    _Data 
    = new byte[_DataLength];
                    System.Array.Copy(old, _Data, _DataLength);
                }

                
    if (CalcHashAfterRead)
                    CalcHash();
                
    return _DataLength;
            }

            
    /// <summary>
            
    /// 计算校验值
            
    /// </summary>
            
    /// <returns>校验值</returns>

            public byte[] CalcHash()
            
    {
                
    return _DataHash = _Data.GetHash();
            }

            
    /// <summary>
            
    /// 将该区块写入文件
            
    /// </summary>

            public void Write()
            
    {
                
    lock (_FileStream)
                
    {
                    _FileStream.Position 
    = (long)Index * (long)Consts.BlockSize;
                    _FileStream.Write(_Data, 
    0, _DataLength);
                }

            }

            
    /// <summary>
            
    /// 转化为二进制数据以传输
            
    /// </summary>
            
    /// <returns></returns>

            public byte[] GetBytes()
            
    {
                MemoryStream mStream 
    = new MemoryStream(1 + 4 + 4 + _DataLength);
                
    byte[] Header = new byte[1{ Consts.FileBlockHeader };
                mStream.Write(Header, 
    01);
                mStream.Write(BitConverter.GetBytes(Index), 
    04);
                mStream.Write(_DataHash, 
    04);
                mStream.Write(_Data, 
    0, _DataLength);
                
    return mStream.ToArray();
            }

            
    int System.IComparable<FileBlock>.CompareTo(FileBlock obj)
            
    {
                
    return (Index as IComparable<int>).CompareTo(obj.Index);
            }

        }

        
    #endregion


        
    #region 事件参数类
        
    public class BlockFinishedEventArgs : EventArgs
        
    {
            
    public int BlockIndex getset; }
            
    public BlockFinishedEventArgs(int BlockIndex) this.BlockIndex = BlockIndex; }
        }

        
    public class CommandReceivedEventArgs : EventArgs
        
    {
            
    public string CommandLine getset; }
            
    public CommandReceivedEventArgs(string CommandLine) this.CommandLine = CommandLine; }
        }

        
    public class FileTransmissionErrorOccurEventArgs : EventArgs
        
    {
            
    public Exception InnerException getset; }
            
    /// <summary>
            
    /// 指示是否继续运行
            
    /// </summary>

            public bool Continue getset; }
            
    public FileTransmissionErrorOccurEventArgs(Exception innerException)
            
    {
                InnerException 
    = innerException;
                Continue 
    = false;
            }

        }

        
    #endregion


        
    #region 文件区块抽象集合类
        
    /// <summary>
        
    /// 文件区块的抽象集合
        
    /// 之所以说抽象是因为该集合并不存储实际的区块(缓存区除外)
        
    /// 而是通过一个索引器来读写文件
        
    /// 并提供磁盘缓存
        
    /// </summary>

        public class FileBlockCollection
        
    {
            
    /// <summary>
            
    /// 与该区块关联的传输对象
            
    /// </summary>

            internal FileTransmission _Task;
            
    /// <summary>
            
    /// 与该区块关联的FileStream
            
    /// </summary>

            internal FileStream _FileStream;
            
    internal bool _EnabledIOBuffer;
            
    /// <summary>
            
    /// 磁盘缓存区
            
    /// </summary>

            internal Dictionary<int, FileBlock> _IOBuffer;

            
    public FileBlockCollection(FileTransmission TransmissionTask)
            
    {
                _Task 
    = TransmissionTask;
                _FileStream 
    = _Task.FileStream;
                _IOBufferSize 
    = Consts.DefaultIOBufferSize;
            }

            
    /// <summary>
            
    /// 获取或设置一个值,该值指示是否启用磁盘缓存
            
    /// </summary>

            internal bool EnabledIOBuffer
            
    {
                
    get return _EnabledIOBuffer; }
                
    set
                
    {
                    _EnabledIOBuffer 
    = value;
                    
    if (value)
                        _IOBuffer 
    = new Dictionary<int, FileBlock>();
                    
    else
                    
    {
                        
    if (_Task is FileReceiver)
                            WriteAllBlock();
                        _IOBuffer 
    = null;
                    }

                }

            }

            
    internal int _IOBufferSize;
            
    /// <summary>
            
    /// 获取已接收或已发送的区块序号列表
            
    /// </summary>

            public List<int> Finished get return _Task._FinishedBlock; } }
            
    /// <summary>
            
    /// 获取已存在(Hash成功)的区块序号列表
            
    /// </summary>

            public List<int> Exist
            
    {
                
    get
                
    {
                    
    if (_Task is FileReceiver)
                        
    return ((FileReceiver)_Task)._ExistBlock;
                    
    else
                        
    return null;
                }

            }

            
    /// <summary>
            
    /// 获取被丢弃的区块序号列表
            
    /// </summary>

            public List<int> Cast
            
    {
                
    get
                
    {
                    
    if (_Task is FileReceiver)
                        
    return ((FileReceiver)_Task)._CastBlock;
                    
    else
                        
    return null;
                }

            }

            
    /// <summary>
            
    /// 获取总区块数
            
    /// </summary>

            public int Count get return _Task._TotalBlock; } }
            
    /// <summary>
            
    /// 获取有效区块数(已存在+已接收)
            
    /// </summary>

            public int CountValid
            
    {
                
    get
                
    {
                    
    if (_Task is FileReceiver)
                        
    return _Task._FinishedBlock.Count + ((FileReceiver)_Task)._ExistBlock.Count;
                    
    else
                        
    return _Task._FinishedBlock.Count;

                }

            }

            
    /// <summary>
            
    /// 将缓存中的区块全部写入磁盘
            
    /// </summary>
            
    /// <returns>写入的区块数量</returns>

            public int WriteAllBlock()
            
    {
                
    if (!_EnabledIOBuffer)
                    
    return -1;
                
    int count = 0;
                
    lock (_IOBuffer)
                
    {
                    
    foreach (var b in _IOBuffer)
                    
    {
                        b.Value.Write();
                        count
    ++;
                    }

                    
    if (count != _IOBuffer.Count)
                        
    throw new IOException("Can not Write All FileBlocks!");
                    _IOBuffer.Clear();
                }

                
    return count;
            }

            
    /// <summary>
            
    /// 读取数据以填充缓存
            
    /// </summary>
            
    /// <param name="StartIndex">起始区块</param>
            
    /// <returns>读取的区块数量</returns>

            public int FillIOBuffer(int StartIndex)
            
    {
                
    int Index;
                
    lock (_IOBuffer)
                
    {
                    _IOBuffer.Clear();
                    
    for (Index = StartIndex; _IOBuffer.Count < _IOBufferSize && Index < _Task.Blocks.Count; Index++)
                    
    {
                        _IOBuffer.Add(Index, 
    new FileBlock(_Task, Index, true));
                    }

                }

                
    return Index - StartIndex;
            }

            
    /// <summary>
            
    /// 异步填充缓存
            
    /// </summary>
            
    /// <param name="StartIndex">起始区块</param>

            public IAsyncResult BeginFillIOBuffer(int StartIndex,AsyncCallback callback,object state)
            
    {
                
    return new Delegate_Int_Int(FillIOBuffer).BeginInvoke(StartIndex, callback, state);
            }

            
    /// <summary>
            
    /// 写入区块
            
    /// </summary>
            
    /// <param name="value">区块对象</param>

            public void Write(FileBlock value)
            
    {
                
    if (_EnabledIOBuffer)
                
    {
                    
    if (_IOBuffer.Count >= _IOBufferSize)
                        WriteAllBlock();
                    
    lock (_IOBuffer)
                        _IOBuffer.Add(value.Index, value);
                }

                
    else
                    value.Write();
            }

            
    /// <summary>
            
    /// 读取或写入区块
            
    /// </summary>
            
    /// <param name="BlockIndex">区块序号</param>

            public FileBlock this[int BlockIndex]
            
    {
                
    get
                
    {
                    FileBlock output;
                    
    if (_EnabledIOBuffer)
                    
    {
                        
                        
    bool IsInBuf;
                        
    lock (_IOBuffer)
                            IsInBuf 
    = _IOBuffer.TryGetValue(BlockIndex, out output);
                        
    if (IsInBuf)
                            
    return output;
                        
    else
                        
    {
                            output 
    = new FileBlock(_Task, BlockIndex, true);
                            BeginFillIOBuffer(BlockIndex 
    + 1nullnull);
                        }

                    }

                    
    else
                        output 
    = new FileBlock(_Task, BlockIndex, true);
                    
    return output;
                }

                
    set
                
    {
                    
    if (BlockIndex != value.Index)
                        
    throw new FileBlockException("Bad Index!", FileBlockException.ErrorCode.BadIndex);
                    Write(value);
                }

            }

        }

        
    #endregion


        
    #region 文件传输基类
        
    public abstract class FileTransmission : IDisposable
        
    {
            
    internal FileStream _FileStream;
            
    //internal readonly TransmissionMode _Mode;
            /// <summary>
            
    /// 总区块数
            
    /// </summary>

            internal int _TotalBlock;
            
    /// <summary>
            
    /// 最后一个区块的大小
            
    /// </summary>

            internal int _LastBlockSize;
            
    internal List<int> _FinishedBlock;
            
    internal byte[] ReceiveBuf;
            
    internal Socket _Socket;
            
    internal EventWaitHandle _WaitHandle;
            
    internal bool _IsAlive;
            
    internal FileBlockCollection _Blocks;
            
    internal DateTime _StartTime;
            
    /// <summary>
            
    /// 上一个区块完成的时间
            
    /// </summary>

            internal DateTime _PriorBlockTime;
            
    internal double _ByteSpeed;
            
    /// <summary>
            
    /// 获取或设置一个值,该值指示是否启用磁盘缓存
            
    /// </summary>

            public bool EnabledIOBuffer
            
    {
                
    get return _Blocks._EnabledIOBuffer; }
                
    set { _Blocks.EnabledIOBuffer = value; }
            }

            
    /// <summary>
            
    /// 获取或设置磁盘缓存的大小(单位:区块数)
            
    /// </summary>

            public int IOBufferSize
            
    {
                
    get return _Blocks._IOBufferSize; }
                
    set
                
    {
                    
    if (!_Blocks._EnabledIOBuffer)
                        
    throw new InvalidOperationException("IOBuffer is not enabled!");
                    _Blocks._IOBufferSize 
    = value;
                }

            }

            
    /// <summary>
            
    /// 获取当前磁盘缓存中的区块数
            
    /// </summary>

            public int CurrentIOBufferSize
            
    {
                
    get
                
    {
                    
    if (!_Blocks._EnabledIOBuffer)
                        
    return 0;
                    
    return _Blocks._IOBuffer.Count;
                }

            }

            
    /// <summary>
            
    /// 获取或设置该传输的目标连接
            
    /// </summary>

            public Socket Socket
            
    {
                
    get return _Socket; }
                
    set
                
    {
                    
    try
                    
    {
                        
    if (value.ProtocolType != ProtocolType.Tcp)
                            
    throw new ArgumentException("Socket Protocol must be TCP""Socket");
                        _Socket 
    = value;
                        _Socket.ReceiveBufferSize 
    = _Socket.SendBufferSize = Consts.NetBlockMaxSize;
                    }

                    
    catch (Exception ex)
                    
    {
                        OnErrorOccurred(ex);
                    }

                }

            }

            
    /// <summary>
            
    /// 获取与此传输关联的文件流
            
    /// </summary>

            public FileStream FileStream get return _FileStream; } }
            
    /// <summary>
            
    /// 获取或设置文件路径
            
    /// </summary>

            public string FilePath getset; }
            
    /// <summary>
            
    /// 获取或设置文件名
            
    /// </summary>

            public string FileName getset; }
            
    /// <summary>
            
    /// 获取或设置文件名(包括路径)
            
    /// </summary>

            public string FullFileName
            
    {
                
    get
                
    {
                    
    try
                    
    {
                        
    return FilePath.TrimEnd('\'+ "\" + FileName;
                    }

                    
    catch (Exception ex)
                    
    {
                        OnErrorOccurred(ex);
                        
    return null;
                    }

                }

                
    set
                
    {
                    
    try
                    
    {
                        
    int i = value.LastIndexOf('\');
                        
    if (i > 0)
                            FilePath 
    = value.Substring(0, i);
                        
    else
                            FilePath 
    = Environment.CurrentDirectory;
                        FileName 
    = value.Substring(i + 1);
                    }

                    
    catch (Exception ex)
                    
    {
                        OnErrorOccurred(ex);
                    }

                }

            }

            
    /// <summary>
            
    /// 一个区块完成时发生
            
    /// </summary>

            public event BlockFinishedEventHandler BlockFinished;
            
    /// <summary>
            
    /// 全部完成时发生
            
    /// </summary>

            public event EventHandler AllFinished;
            
    /// <summary>
            
    /// 连接中断时发生
            
    /// </summary>

            public event EventHandler ConnectLost;
            
    /// <summary>
            
    /// 出现错误时发生
            
    /// </summary>

            public event FileTransmissionErrorOccurEventHandler ErrorOccurred;
            
    /// <summary>
            
    /// 获取一个值,该值指示传输是否正在进行
            
    /// </summary>

            public bool IsAlive get return _IsAlive; } }
            
    /// <summary>
            
    /// 获取传输开始的时间
            
    /// </summary>

            public DateTime StartTime get return _StartTime; } }
            
    /// <summary>
            
    /// 获取已用时
            
    /// </summary>

            public TimeSpan TimePast get return DateTime.Now - _StartTime; } }
            
    /// <summary>
            
    /// 获取估计剩余时间
            
    /// </summary>

            public abstract TimeSpan TimeRemaining get; }
            
    /// <summary>
            
    /// 获取平均速率(区块/秒)
            
    /// </summary>

            public double BlockAverSpeed
            
    {
                
    get
                
    {
                    
    return _FinishedBlock.Count / TimePast.TotalSeconds;
                }

            }

            
    /// <summary>
            
    /// 获取平均速率(字节/秒)
            
    /// </summary>

            public double ByteAverSpeed
            
    {
                
    get
                
    {
                    
    return BlockAverSpeed * Consts.BlockSize;
                }

            }

            
    /// <summary>
            
    /// 获取平均速率(千字节/秒)
            
    /// </summary>

            public double KByteAverSpeed
            
    {
                
    get
                
    {
                    
    return ByteAverSpeed / 1024;
                }

            }

            
    /// <summary>
            
    /// 获取瞬时速率(字节/秒)
            
    /// </summary>

            public double ByteSpeed
            
    {
                
    get
                
    {
                    
    return _ByteSpeed;
                }

            }

            
    /// <summary>
            
    /// 获取瞬时速率(千字节/秒)
            
    /// </summary>

            public double KByteSpeed
            
    {
                
    get
                
    {
                    
    return _ByteSpeed / 1024;
                }

            }

            
    /// <summary>
            
    /// 获取文件总长度
            
    /// </summary>

            public long TotalSize
            
    {
                
    get
                
    {
                    
    return (long)(_TotalBlock - 1* (long)Consts.BlockSize + (long)_LastBlockSize;
                }

            }

            
    /// <summary>
            
    /// 获取已完成的数据长度
            
    /// </summary>

            public abstract long FinishedSize get; }
            
    /// <summary>
            
    /// 获取进度值(%)
            
    /// </summary>

            public double Progress
            
    {
                
    get
                
    {
                    
    return ((double)FinishedSize / (double)TotalSize) * 100;
                }

            }

            
    /// <summary>
            
    /// 获取该传输的区块集合
            
    /// </summary>

            public FileBlockCollection Blocks get return _Blocks; } }
            
    /// <summary>
            
    /// 默认构造函数
            
    /// </summary>

            public FileTransmission()
            
    {
                _FinishedBlock 
    = new List<int>();
                _WaitHandle 
    = new EventWaitHandle(false, EventResetMode.ManualReset);
                _Blocks 
    = new FileBlockCollection(this);
            }

            
    /// <summary>
            
    /// 构造函数
            
    /// </summary>
            
    /// <param name="FilePath">文件路径</param>
            
    /// <param name="FileName">文件名</param>

            public FileTransmission(string FilePath, string FileName)
            
    {
                _FinishedBlock 
    = new List<int>();
                _WaitHandle 
    = new EventWaitHandle(true, EventResetMode.ManualReset);
                _Blocks 
    = new FileBlockCollection(this);

                
    this.FilePath = FilePath;
                
    this.FileName = FileName;
            }

            
    /// <summary>
            
    /// 初始化接收缓存
            
    /// </summary>

            internal void InitializeReceiveBuf()
            
    {
                
    try
                
    {
                    ReceiveBuf 
    = new byte[_Socket.ReceiveBufferSize];
                }

                
    catch (Exception ex)
                
    {
                    OnErrorOccurred(ex);
                }

            }

            
    /// <summary>
            
    /// 开始异步接收
            
    /// </summary>

            internal abstract IAsyncResult BeginReceive();
            
    /// <summary>
            
    /// 开始传输
            
    /// </summary>

            public virtual void Start()
            
    {
                
    try
                
    {
                    _IsAlive 
    = true;
                    _StartTime 
    = DateTime.Now;
                    _WaitHandle.Reset();
                }

                
    catch (Exception ex)
                
    {
                    OnErrorOccurred(ex);
                }

            }

            
    /// <summary>
            
    /// 中止传输
            
    /// </summary>
            
    /// <param name="ShutDownSocket">是否关闭Socket</param>

            public virtual void Stop(bool ShutDownSocket)
            
    {
                
    try
                
    {
                    _IsAlive 
    = false;
                    _FileStream.Close();
                    _FileStream 
    = null;
                    _WaitHandle.Set();
                    
    if (ShutDownSocket)
                    
    {
                        _Socket.Shutdown(SocketShutdown.Both);
                        _Socket.Close();
                    }

                }

                
    catch (Exception ex)
                
    {
                    OnErrorOccurred(ex);
                }

            }

            
    /// <summary>
            
    /// 异步中止传输,不关闭Socket
            
    /// </summary>

            internal void Stop()
            
    {
                
    new Delegate_Void_Bool(Stop).BeginInvoke(falsenullnull);
            }

            
    /// <summary>
            
    /// 等待传输完成
            
    /// </summary>

            public bool WaitForExit()
            
    {
                
    return _WaitHandle.WaitOne();
            }

            
    /// <summary>
            
    /// 等待传输完成
            
    /// </summary>

            public bool WaitForExit(int millisecondsTimeout, bool exitContext)
            
    {
                
    return _WaitHandle.WaitOne(millisecondsTimeout, exitContext);
            }

            
    /// <summary>
            
    /// 等待传输完成
            
    /// </summary>

            public bool WaitForExit(TimeSpan timeout, bool exitContext)
            
    {
                
    return _WaitHandle.WaitOne(timeout, exitContext);
            }

            
    internal virtual void OnBlockFinished(int BlockIndex)
            
    {
                
    if (!_FinishedBlock.Exists(a => a == BlockIndex))
                    _FinishedBlock.Add(BlockIndex);
                
    if (BlockIndex == _TotalBlock - 1)
                    _ByteSpeed 
    = _LastBlockSize / (DateTime.Now - _PriorBlockTime).TotalSeconds;
                
    else
                    _ByteSpeed 
    = Consts.BlockSize / (DateTime.Now - _PriorBlockTime).TotalSeconds;
                _PriorBlockTime 
    = DateTime.Now;
                
    if (BlockFinished != null)
                    BlockFinished(
    thisnew BlockFinishedEventArgs(BlockIndex));
            }

            
    internal virtual void OnConnectLost()
            
    {
                
    if (!_IsAlive)
                    
    return;
                Stop();
                
    if (ConnectLost != null)
                    ConnectLost(
    thisnew EventArgs());
            }

            
    /// <summary>
            
    /// 同步发送字符串
            
    /// </summary>

            public int SendString(string str)
            
    {
                
    try
                
    {
                    
    return _Socket.EndSend(BeginSendString(str, nullnull));
                }

                
    catch (SocketException)
                
    {
                    OnConnectLost();
                    
    return 0;
                }

                
    catch (Exception ex)
                
    {
                    OnErrorOccurred(ex);
                    
    return 0;
                }

            }

            
    /// <summary>
            
    /// 异步发送字符串并使用默认的回调方法
            
    /// </summary>

            public void SendStringAsync(string str)
            
    {
                BeginSendString(str, SendCallback, 
    null);
            }

            
    /// <summary>
            
    /// 异步发送字符串并使用指定的的回调方法和参数
            
    /// </summary>

            public IAsyncResult BeginSendString(string str, AsyncCallback callback, object state)
            
    {
                
    try
                
    {
                    
    if (!_IsAlive)
                        
    throw new InvalidOperationException("Is Not Alive");
                    
    byte[] ToSend = str.ToBytes();
                    
    return _Socket.BeginSend(ToSend, 0, ToSend.Length, SocketFlags.None, callback, state);
                }

                
    catch (SocketException)
                
    {
                    OnConnectLost();
                    
    return null;
                }

                
    catch (Exception ex)
                
    {
                    OnErrorOccurred(ex);
                    
    return null;
                }

            }

            
    internal void SendCallback(IAsyncResult ar)
            
    {
                
    try
                
    {
                    _Socket.EndSend(ar);
                }

                
    catch (SocketException)
                
    {
                    OnConnectLost();
                }

                
    catch (Exception ex)
                
    {
                    OnErrorOccurred(ex);
                }

                
    if (ar.AsyncState != null)
                
    {
                    
    if (ar.AsyncState is int)
                    
    {
                        OnBlockFinished((
    int)ar.AsyncState);
                    }

                }

            }

            
    internal virtual void OnAllFinished()
            
    {
                
    if (AllFinished != null)
                    AllFinished(
    thisnew EventArgs());
            }

            
    internal virtual void OnErrorOccurred(Exception innerException)
            
    {
                FileTransmissionErrorOccurEventArgs eventargs 
    = new FileTransmissionErrorOccurEventArgs(innerException);
                
    if (ErrorOccurred != null)
                    ErrorOccurred(
    this, eventargs);
                
    if (!eventargs.Continue)
                    
    throw innerException;
            }

            
    void System.IDisposable.Dispose()
            
    {
                _FileStream.Close();
                _Socket.Close();
            }

        }

        
    #endregion


        
    #region 发送端类
        
    /// <summary>
        
    /// 发送端
        
    /// 传输前发送端创建该类实例
        
    /// 设置必要属性后
        
    /// 调用Start()方法开始传输
        
    /// </summary>

        public class FileSender : FileTransmission
        
    {
            
    /// <summary>
            
    /// 接收到命令时发生
            
    /// </summary>

            public event CommandReceivedEventHandler CommandReceived;
            
    /// <summary>
            
    /// 开始异步接收
            
    /// </summary>

            internal override IAsyncResult BeginReceive()
            
    {
                InitializeReceiveBuf();
                
    try
                
    {
                    
    return _Socket.BeginReceive(ReceiveBuf, 0, ReceiveBuf.Length, SocketFlags.None, ReceiveCallback, null);
                }

                
    catch (SocketException)
                
    {
                    OnConnectLost();
                    
    return null;
                }

                
    catch (Exception ex)
                
    {
                    OnErrorOccurred(ex);
                    
    return null;
                }

            }

            
    /// <summary>
            
    /// 开始传输
            
    /// </summary>

            public override void Start()
            
    {
                
    base.Start();
                
    try
                
    {
                    BeginReceive();
                    _FileStream 
    = new FileStream(FullFileName, FileMode.Open, FileAccess.Read, FileShare.Read);
                    _TotalBlock 
    = (int)(_FileStream.Length / (long)Consts.BlockSize) + 1;
                    _LastBlockSize 
    = (int)(_FileStream.Length - ((long)_TotalBlock - 1* (long)Consts.BlockSize);
                }

                
    catch (Exception ex)
                
    {
                    OnErrorOccurred(ex);
                }

            }

            
    /// <summary>
            
    /// 获取估计剩余时间
            
    /// </summary>

            public override TimeSpan TimeRemaining
            
    {
                
    get
                
    {
                    
    int BlockRemaining = _TotalBlock - _FinishedBlock.Count;
                    
    return TimeSpan.FromSeconds(BlockRemaining / BlockAverSpeed);
                }

            }

            
    /// <summary>
            
    /// 获取已完成的数据长度
            
    /// </summary>

            public override long FinishedSize
            
    {
                
    get
                
    {
                    
    return (long)_FinishedBlock.Count * (long)Consts.BlockSize;
                }

            }

            
    /// <summary>
            
    /// 同步发送区块
            
    /// </summary>
            
    /// <param name="BlockIndex">区块序号</param>
            
    /// <returns>发送的数据长度</returns>

            public int SendBlock(int BlockIndex)
            
    {
                
    try
                
    {
                    
    int ret = _Socket.EndSend(BeginSendBlock(BlockIndex, nullnull));
                    OnBlockFinished(BlockIndex);
                    
    return ret;
                }

                
    catch (SocketException)
                
    {
                    OnConnectLost();
                    
    return 0;
                }

                
    catch (Exception ex)
                
    {
                    OnErrorOccurred(ex);
                    
    return 0;
                }

            }

            
    /// <summary>
            
    /// 异步发送区块并使用默认的回调方法
            
    /// </summary>
            
    /// <param name="BlockIndex">区块序号</param>

            public void SendBlockAsync(int BlockIndex)
            
    {
                BeginSendBlock(BlockIndex, SendCallback, BlockIndex);
            }

            
    /// <summary>
            
    /// 异步发送区块并使用指定的回调方法和参数
            
    /// </summary>
            
    /// <param name="BlockIndex">区块序号</param>

            public IAsyncResult BeginSendBlock(int BlockIndex, AsyncCallback callback, object state)
            
    {
                
    try
                
    {
                    
    if (!_IsAlive)
                        
    throw new InvalidOperationException("Is Not Alive");
                    
    if (BlockIndex >= _TotalBlock)
                        
    throw new ArgumentOutOfRangeException("BlockIndex");
                    
    byte[] ToSend = _Blocks[BlockIndex].GetBytes();
                    
    return _Socket.BeginSend(ToSend, 0, ToSend.Length, SocketFlags.None, callback, state);
                }

                
    catch (SocketException)
                
    {
                    OnConnectLost();
                    
    return null;
                }

                
    catch (Exception ex)
                
    {
                    OnErrorOccurred(ex);
                    
    return null;
                }

            }

            
    internal void ReceiveCallback(IAsyncResult ar)
            
    {
                
    bool ContinueReceive = true;
                
    int count = 0;
                
    try
                
    {
                    count 
    = _Socket.EndReceive(ar);
                }

                
    catch (SocketException)
                
    {
                    OnConnectLost();
                    
    return;
                }

                
    catch (Exception ex)
                
    {
                    
    try
                    
    {
                        OnErrorOccurred(ex);
                    }

                    
    catch return; }
                }

                
    try
                
    {
                    
    if (count == 0)
                        
    return;
                    
    switch (ReceiveBuf[0])
                    
    {
                        
    case Consts.StringHeader:
                            ContinueReceive 
    = OnCommandReceived(ReceiveBuf.ToFTString());
                            
    break;
                        
    default:
                            
    throw new FormatException("Bad Header!");
                    }

                }

                
    catch (Exception ex)
                
    {
                    OnErrorOccurred(ex);
                }

                
    if (ContinueReceive)
                
    {
                    BeginReceive();
                }

            }

            
    /// <summary>
            
    /// 命令处理
            
    /// </summary>
            
    /// <param name="str">收到的命令</param>
            
    /// <returns>是否继续接收</returns>

            internal bool OnCommandReceived(string str)
            
    {
                
    if (CommandReceived != null)
                    CommandReceived(
    thisnew CommandReceivedEventArgs(str));
                
    bool ContinueReceive = true;
                
    string[] Msg = str.Split(' ');
                
    if (Msg[0== "Exit")
                
    {
                    OnAllFinished();
                    ContinueReceive 
    = false;
                    Stop();
                }

                
    else if (Msg[0== "GET")
                
    {
                    
    if (Msg[1== "FileBlock")
                    
    {
                        
    int BlockIndex;
                        
    if (!int.TryParse(Msg[2], out BlockIndex))
                            
    throw new FormatException("Bad BlockIndex " + Msg[2]);
                        SendBlock(BlockIndex);
                    }

                    
    else if (Msg[1== "BlockHash")
                    
    {
                        
    int BlockIndex;
                        
    if (!int.TryParse(Msg[2], out BlockIndex))
                            
    throw new FormatException("Bad BlockIndex " + Msg[2]);
                        
    byte[] hash = _Blocks[BlockIndex].DataHash;
                        SendStringAsync(
    string.Format("BlockHash {0} {1}", BlockIndex, BitConverter.ToInt32(hash, 0)));
                    }

                    
    else if (Msg[1== "FileName")
                    
    {
                        SendStringAsync(
    string.Format("SET FileName {0}", FileName.DoReplace()));
                    }

                    
    else if (Msg[1== "TotalBlock")
                    
    {
                        SendStringAsync(
    string.Format("SET TotalBlock {0}", _TotalBlock));
                    }

                    
    else if (Msg[1== "LastBlockSize")
                    
    {
                        SendStringAsync(
    string.Format("SET LastBlockSize {0}", _LastBlockSize));
                    }

                    
    else
                        
    throw new FormatException("Bad Command " + Msg[1]);
                }

                
    else
                    
    throw new FormatException("Bad Command " + Msg[0]);

                
    return ContinueReceive;
            }

        }

        
    #endregion


        
    #region 接收端类
        
    /// <summary>
        
    /// 接收端
        
    /// 传输前接收端创建该类实例
        
    /// 设置必要属性后
        
    /// 调用Start()方法开始传输
        
    /// </summary>

        public class FileReceiver : FileTransmission
        
    {
            
    internal List<int> _ExistBlock;
            
    internal List<int> _CastBlock;
            
    /// <summary>
            
    /// 下载线程
            
    /// </summary>

            internal Thread _DownThread;
            
    public event BlockFinishedEventHandler BlockHashed;
            
    /// <summary>
            
    /// 开始异步接收
            
    /// </summary>

            internal override IAsyncResult BeginReceive()
            
    {
                InitializeReceiveBuf();
                
    try
                
    {
                    
    return _Socket.BeginReceive(ReceiveBuf, 0, ReceiveBuf.Length, SocketFlags.None, nullnull);
                }

                
    catch (SocketException)
                
    {
                    OnConnectLost();
                    
    return null;
                }

                
    catch (Exception ex)
                
    {
                    OnErrorOccurred(ex);
                    
    return null;
                }

            }

            
    /// <summary>
            
    /// 获取估计剩余时间
            
    /// </summary>

            public override TimeSpan TimeRemaining
            
    {
                
    get
                
    {
                    
    int BlockRemaining = _TotalBlock - _FinishedBlock.Count - ((FileReceiver)this)._ExistBlock.Count;
                    
    return TimeSpan.FromSeconds(BlockRemaining / BlockAverSpeed);
                }

            }

            
    /// <summary>
            
    /// 获取已完成的数据长度
            
    /// </summary>

            public override long FinishedSize
            
    {
                
    get
                
    {
                    
    return ((long)_FinishedBlock.Count + (long)_ExistBlock.Count - 1* (long)Consts.BlockSize + (long)_LastBlockSize;
                }

            }

            
    /// <summary>
            
    /// 开始传输
            
    /// </summary>

            public override void Start()
            
    {
                
    base.Start();
                
    try
                
    {
                    _CastBlock 
    = new List<int>();
                    _ExistBlock 
    = new List<int>();
                    _DownThread 
    = new Thread(DownLoad);
                    _DownThread.IsBackground 
    = true;
                    _DownThread.Name 
    = "DownThread";
                    _DownThread.Start();
                }

                
    catch (Exception ex)
                
    {
                    OnErrorOccurred(ex);
                }

            }

            
    /// <summary>
            
    /// 中止传输
            
    /// </summary>
            
    /// <param name="ShutDownSocket">是否关闭Socket</param>

            public override void Stop(bool ShutDownSocket)
            
    {
                
    try
                
    {
                    
    if (_DownThread != null)
                    
    {
                        
    if ((_DownThread.ThreadState & ThreadState.Running) == ThreadState.Running)
                            _DownThread.Abort();
                    }

                }

                
    catch (Exception ex)
                
    {
                    OnErrorOccurred(ex);
                }

                
    base.Stop(ShutDownSocket);
            }

            
    internal string ReceiveString()
            
    {
                
    int count = 0;
                
    try
                
    {
                    count 
    = _Socket.EndReceive(BeginReceive());
                }

                
    catch (Exception ex)
                
    {
                    OnConnectLost();
                    
    throw ex;
                }

                
    if (count == 0)
                    
    return null;
                
    else
                    
    return ReceiveBuf.ToFTString();
            }

            
    internal FileBlock ReceiveFileBlock()
            
    {
                MemoryStream mStream 
    = new MemoryStream();
                
    while (true)
                
    {
                    
    int count = 0;
                    
    try
                    
    {
                        count 
    = _Socket.EndReceive(BeginReceive());
                        
    if (count == 0throw new Exception();
                    }

                    
    catch (Exception ex)
                    
    {
                        OnConnectLost();
                        
    throw ex;
                    }

                    mStream.Write(ReceiveBuf, 
    0, count);
                    
    try
                    
    {//接收到正确的区块则返回
                        return new FileBlock(this, mStream.ToArray());
                    }

                    
    catch (FileBlockException ex)
                    
    {//接收到不完整或错误的区块,若不完整则继续接收
                        if (mStream.Length >= Consts.NetBlockMaxSize)
                            
    throw ex;//区块已达到指定大小但仍然错误,则抛出错误
                    }

                }

            }

            
    /// <summary>
            
    /// 从发送端获取文件名
            
    /// </summary>

            public void GetFileName()
            
    {
                
    while (true)
                
    {
                    SendString(
    "GET FileName");
                    
    string[] Msg = ReceiveString().Split(' ');
                    
    if (Msg[0== "SET" && Msg[1== "FileName")
                    
    {
                        FileName 
    = Msg[2];
                        
    break;
                    }

                }

            }

            
    /// <summary>
            
    /// 从发送端获取区块总数
            
    /// </summary>

            public void GetTotalBlock()
            
    {
                
    while (true)
                
    {
                    SendString(
    "GET TotalBlock");
                    
    string[] Msg = ReceiveString().Split(' ');
                    
    if (Msg[0== "SET" && Msg[1== "TotalBlock")
                    
    {
                        
    if (int.TryParse(Msg[2], out _TotalBlock))
                            
    break;
                    }

                }

            }

            
    /// <summary>
            
    /// 从发送端获取最后一个区块的大小
            
    /// </summary>

            public void GetLastBlockSize()
            
    {
                
    while (true)
                
    {
                    SendString(
    "GET LastBlockSize");
                    
    string[] Msg = ReceiveString().Split(' ');
                    
    if (Msg[0== "SET" && Msg[1== "LastBlockSize")
                    
    {
                        
    if (int.TryParse(Msg[2], out _LastBlockSize))
                            
    break;
                    }

                }

            }

            
    /// <summary>
            
    /// 校验文件
            
    /// </summary>
            
    /// <returns>损坏或尚未下载的区块序号列表</returns>

            public List<int> HashFile()
            
    {
                _FileStream.Position 
    = 0;
                _ExistBlock.Clear();
                
    for (int count = 0; _FileStream.Position < _FileStream.Length && count < _TotalBlock; count++)
                
    {//校验已存在的区块
                    FileBlock TestBlock = new FileBlock(this, count, true);
                    SendString(
    string.Format("GET BlockHash {0}", count));
                    
    string[] Msg = ReceiveString().Split(' ');
                    
    if (Msg[0== "BlockHash")
                    
    {
                        
    if (Convert.ToInt32(Msg[1]) == count)
                        
    {
                            
    if (BitConverter.ToInt32(TestBlock.DataHash, 0== Convert.ToInt32(Msg[2]))
                                _ExistBlock.Add(count);
                        }

                    }

                    
    if (BlockHashed != null)
                        BlockHashed(
    thisnew BlockFinishedEventArgs(count));
                }

                
    int MaxExistBlockIndex;//已存在的区块最大序号
                try
                
    {
                    MaxExistBlockIndex 
    = _ExistBlock.Max();
                }

                
    catch
                
    {
                    MaxExistBlockIndex 
    = 0;
                }

                List
    <int> BlockRemaining = new List<int>();
                
    for (int index = 0; index < _TotalBlock; )
                
    {//计算仍需传输的区块
                    if (index <= MaxExistBlockIndex)
                    
    {
                        
    if (_ExistBlock.Exists(a => a == index))
                        
    {
                            index
    ++;
                            
    continue;
                        }

                    }

                    BlockRemaining.Add(index
    ++);
                }

                
    return BlockRemaining;
            }

            
    /// <summary>
            
    /// 接收整个文件
            
    /// </summary>

            internal void DownLoad()
            
    {
                
    try
                
    {
                    
    if (string.IsNullOrEmpty(FilePath))//未指定路径时默认为接收程序所在路径
                        FilePath = Environment.CurrentDirectory;
                    
    if (string.IsNullOrEmpty(FileName))//未指定文件名时从发送端获取
                    {
                        GetFileName();
                    }

                    _FileStream 
    = new FileStream(FullFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);//temp
                    GetTotalBlock();
                    GetLastBlockSize();
                    List
    <int> BlockRemaining = HashFile();
                    
    if (_FileStream.Length > TotalSize)//如果已存在的文件比目标文件长则截断它
                        _FileStream.SetLength(TotalSize);
                    _StartTime 
    = DateTime.Now;
                    
    foreach (int index in BlockRemaining)
                    
    {
                        FileBlock Block;
                        
    while (true)
                        
    {
                            SendString(
    string.Format("GET FileBlock {0}", index));
                            
    try
                            
    {
                                Block 
    = ReceiveFileBlock();
                                
    break;
                            }

                            
    catch (FileBlockException)
                            
    {//接收到错误的区块,抛弃该数据并重新请求
                                _CastBlock.Add(index);
                            }

                            
    catch (Exception ex)
                            
    {
                                OnErrorOccurred(ex);
                            }

                        }

                        
    while (true)
                        
    {
                            
    try
                            
    {
                                _Blocks[index] 
    = Block;//写入区块
                                OnBlockFinished(index);
                                
    break;
                            }

                            
    catch (IOException ex)
                            
    {//磁盘写入错误时
                                try
                                
    {
                                    OnErrorOccurred(ex);
                                    
    //重试
                                }

                                
    catch
                                
    {//退出
                                    Stop();
                                    
    return;
                                }

                            }

                            
    catch (Exception ex)
                            
    {
                                OnErrorOccurred(ex);
                            }

                        }

                    }

                    SendStringAsync(
    "Exit");
                    _Blocks.WriteAllBlock();
                    OnAllFinished();
                    Stop();
                }

                
    catch (SocketException) { }
                
    catch (Exception ex)
                
    {
                    OnErrorOccurred(ex);
                }

            }

        }

        
    #endregion

    }
    复制代码

    VS2008完整项目文件,包括类库和一个简单的Demo:
    /Files/takamachi660/SendFileTest_v0.6.rar

     
     
     
    标签: C#网络
  • 相关阅读:
    cygwin补充安装gcc/g++的方法
    JS中获取request的值,非常好用的JS代码
    登录页面跳出框架的JS
    asp.net DataTable转JSON
    ASP.NET文件下载的实用方法
    史上最牛X到的身份证号码验证,测试误差为0
    nopcommerce插件深度剖析
    C# foreach,linq,delegate集合查询的性能比较
    jquery tab插件精简版
    建议博客园成立中国的开源项目组织,同意的顶起
  • 原文地址:https://www.cnblogs.com/systemnet123/p/3255521.html
Copyright © 2011-2022 走看看