日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

简单实现tcp/ip下的文件断点续传

發布時間:2023/12/29 综合教程 34 生活家
生活随笔 收集整理的這篇文章主要介紹了 简单实现tcp/ip下的文件断点续传 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

其實在tcp/ip協議中傳輸文件可以保證傳輸的有效性,但有一個問題文件傳了一部分連接意外斷開了怎樣;那這種情況只能在重新連接后繼續傳輸,由于文件那部分已經傳了那部分沒有完成并不是tcp/ip的范圍,所以需要自己來制定協議達到到這個目的。實現這個續傳的協議制定其實也是非常簡單,通過協議把文件按塊來劃分,每完成一個塊就打上一個標記;即使是連接斷了通過標記狀態就知道還需要傳那些內容。下面通過beetle來實現一個簡單斷點續傳的程序(包括服務端和客戶端)。

在實現之前先整理一下流程思路,首先提交一個發送請求信息包括(文件名,塊大小,塊的數量等),等對方確認后就進行文件塊發送,對方接收塊寫入后返回一個標記,然后再繼續發直到所有發送完成。思路明確后就制定協了:

文件傳輸申請信息

    public class Post:MessageBase
    {   
        public string FileName;
        public long Size;
        public int PackageSize;
        public int Packages;
        public Post()
        {
            FileID = Guid.NewGuid().ToString("N");
        }
    }
    public class PostResponse : MessageBase
    {
        public string Status; 
    }

FileID這個值是用來協同工作的,兩端根據這個ID來找到具體操作的文件和相關信息;Response提供了一個Status屬性,可以用來提供一個錯誤的描述,如果無有任何值的情況說明對方允許這個行為.

文件塊傳輸信息

    public class PostPackage:MessageBase
    {
        public byte[] Data;
        public int Index;
    }
    public class PostPackageResponse : MessageBase
    {
        public int Index;
        public string Status;
    }

文件塊傳輸也是一個請求,一個應答;分別帶的信息就是塊數據信息和塊的位置,同樣也是根據Status信息來標記塊的處理是否成功。

結構定義完成了,那就進行邏輯處理部分;不過為了調用更方便還需要封裝一些東西,如根據塊大小來劃分文件塊的數目,獲取某一文件塊的內容和寫入文件某一些的內容等功能。

        public static int GetFilePackages(long filesize)
        {
            int count;
            if (filesize % PackageSize > 0)
            {
                count = Convert.ToInt32(filesize / PackageSize) + 1;
            }
            else
            {
                count = Convert.ToInt32(filesize / PackageSize);
            }
           
            return count;
        }
        public static byte[] FileRead(string filename, int index, int size)
        {
            using (Smark.Core.ObjectEnter oe = new Smark.Core.ObjectEnter(filename))
            {
                byte[] resutl = null;
                long length = (long)index * (long)size + size;
                using (System.IO.FileStream stream = System.IO.File.OpenRead(filename))
                {
                    if (length > stream.Length)
                    {
                        resutl = new byte[stream.Length - ((long)index * (long)size)];
                    }
                    else
                    {
                        resutl = new byte[size];
                    }
                    stream.Seek((long)index * (long)size, System.IO.SeekOrigin.Begin);
                    stream.Read(resutl, 0, resutl.Length);
                }
                return resutl;
            }
        }
        public static void FileWrite(string filename, int index, int size, byte[] data)
        {
            using (Smark.Core.ObjectEnter oe = new Smark.Core.ObjectEnter(filename))
            {
                using (System.IO.FileStream stream = System.IO.File.OpenWrite(filename))
                {
                    stream.Seek((long)index * (long)size, System.IO.SeekOrigin.Begin);
                    stream.Write(data, 0, data.Length);
                    stream.Flush();
                }
            }

        }

準備工作完成了,就開始寫接收端的代碼了。之前的文章已經介紹了Beetle如果創建一個服務和綁定分包機制,在這里就不多說了;看下接收的邏輯是怎樣處理了.

接收傳文件請求

        public void Post(ChannelAdapter adapter, Beetle.FileTransfer.Post e)
        {
            string file = txtFolder.Text + e.FileName;
            PostResponse response = new PostResponse();
            response.FileID = e.FileID;
            response.ID = e.ID;
            try
            {
                if (FileTransferUtils.CreateFile(file, e.Size))
                {
                    Logics.FileItem item = new Logics.FileItem();
                    item.FileID = e.FileID;
                    item.FileName = file;
                    item.Packages = e.Packages;
                    item.PackageSize = e.PackageSize;
                    item.Completed = 0;
                    item.Size = e.Size;
                    Logics.Access.Update(item);
                    AddItem(item);
                }
                else
                {
                    response.Status = "不能創建文件!";
                }
            }
            catch (Exception e_)
            {
                response.Status = e_.Message;
            }
            adapter.Send(response);
            
        }

接收請求后根據信息創建臨時文件,創建成功就把文件相關信息保存到數據庫中,如果失敗或處理異常就設置相關Status信息返回.

接收文件塊請求

        public void PostPackage(ChannelAdapter adapter, Beetle.FileTransfer.PostPackage e)
        {
            PostPackageResponse response = new PostPackageResponse();
            response.FileID = e.FileID;
            response.ID = e.ID;
            try
            {
                Logics.FileListItem item = fileListBox1.GetAtFileID(e.FileID);
                if (item != null)
                {
                    FileTransferUtils.FileWrite(
                        item.Item.FileName + ".up", e.Index, item.Item.PackageSize, e.Data);
                    item.Completed(e.Index);
                    response.Index = e.Index;
                    if (item.Status == Logics.FileItemStatus.Completed)
                        FileTransferUtils.Rename(item.Item.FileName);
                }
                else
                {
                    response.Status = "不存在上傳信息!";
                }
            }
            catch (Exception e_)
            {
                response.Status = e_.Message;
            }
            adapter.Send(response);
        }

接收塊請求后處理也很簡單,根據FileID獲取相關信息,然后把數據寫入到文件對應的位置中;當所有塊都已經完成后把臨時文件名改會來就行了。如果處理異常很簡單通過設置到Status成員中告訴請求方。

以下就是請求端的代碼了,其代碼比接收端更加簡單了

        public void PostResponse(ChannelAdapter adapter, Beetle.FileTransfer.PostResponse e)
        {
            mResponse = e;
            mResetEvent.Set();
        }
        public void PostPackageResponse(ChannelAdapter adapter, Beetle.FileTransfer.PostPackageResponse e)
        {
            Logics.FileListItem item = fileListBox1.GetAtFileID(e.FileID);
            if (item != null)
            {
                if (string.IsNullOrEmpty(e.Status))
                {
                    item.Completed(e.Index);
                    PostPacakge(item);
                }
                else
                    item.Status = Logics.FileItemStatus.Default;
            }
        }
        private void PostPacakge(Logics.FileListItem item)
        {
            if (mChannel != null && mChannel.Socket != null && item.Status == Logics.FileItemStatus.Working
                && item.Item.Completed != item.Item.Packages)
            {
                PostPackage post = new PostPackage();
                post.FileID = item.Item.FileID;
                post.Index = item.Item.Completed;
                post.Data = FileTransferUtils.FileRead(item.Item.FileName,
                    item.Item.Completed, item.Item.PackageSize);
                mAdapter.Send(post);
            }
        }

請求端要做的工作就是發送文件傳輸請求,等回應后就處理PostPacakge進行文件塊發送,接收到當前文件塊處理成功后就發送下一塊直接完成。

到這里斷點續傳的功能代碼就已經完成,兩邊的程序已經可以工作。不過對于一些使用者來說希望程序更友好的表現工作情況,這個時候還得對UI下一點功夫,如看到當前傳輸的狀態和每個文件進度情況等。

以上效果看起來很不錯,那接下來就把它實現吧,程序使用ListBox來顯示傳輸文件信息,要達到以上效果需要簡單地重寫一下OnDrawItem達到我們需要的。在講述代碼之前介紹一個圖標網站http://www.iconfinder.com/,畢竟好的圖標可以讓程序生色不少。下面看下這個重寫的代碼:

        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            base.OnDrawItem(e);
            StringFormat ListSF;
            Point imgpoint = new Point(e.Bounds.X + 2, e.Bounds.Y + 1);
            ListSF = StringFormat.GenericDefault;
            ListSF.LineAlignment = StringAlignment.Center;
            ListSF.FormatFlags = StringFormatFlags.LineLimit | StringFormatFlags.NoWrap;
            ListSF.Trimming = StringTrimming.EllipsisCharacter;
            Rectangle labelrect = new Rectangle(e.Bounds.X + 44, e.Bounds.Y, e.Bounds.Width - 44, e.Bounds.Height);
            if (Site == null || Site.DesignMode == false)
            {
                if (e.Index >= 0)
                {
                    FileListItem item = (FileListItem)Items[e.Index];
                    LinearGradientBrush brush;
                    brush =
                      new LinearGradientBrush(e.Bounds, Color.FromArgb(208, 231, 253),
                      Color.FromArgb(10, 94, 177), LinearGradientMode.Horizontal);
                    double pent = (double)item.Item.Completed / (double)item.Item.Packages;
                    using (brush)
                    {
                        e.Graphics.FillRectangle(brush, e.Bounds.X + 40, e.Bounds.Y + 2, Convert.ToInt32((e.Bounds.Width - 40) * pent), e.Bounds.Height - 4);
                    }
                    if (item.Status == FileItemStatus.Working)
                    {
                        mImgList.Draw(e.Graphics, imgpoint, 1);
                    }
                    else if (item.Status == FileItemStatus.Completed)
                    {
                        mImgList.Draw(e.Graphics, imgpoint, 2);
                    }
                    else
                    {
                        mImgList.Draw(e.Graphics, imgpoint, 0);
                    }
                    e.Graphics.DrawString(item.ToString(),new Font("Ariel", 9), new SolidBrush(Color.Black),labelrect, ListSF);
                }
            }
        }

重繪代碼就是根據當前文件的進度內容來計算出填沖的寬度,還有根據當前文件狀態繪制不同的圖標,是不是比較簡單:)

整個功能完成了看下總體的效果怎樣:

下載完整代碼

FileTransfer.rar (649.79 kb)

如果需要Smark名稱空間的代碼可以到http://smark.codeplex.com/

訪問Beetlex的Github

總結

以上是生活随笔為你收集整理的简单实现tcp/ip下的文件断点续传的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产91精品一区二区 | 快播日韩| 玖玖视频网 | 97人人精品| 激情一区二区 | 99精品视频免费看 | 在线免费观看av不卡 | 五月天久久久久 | 国产草草| 在线观看免费的av | 奇米影视在线观看 | 国产1级片 | 国产av人人夜夜澡人人爽 | 综合激情av| 日韩在线视频你懂的 | 嫩草影院污| 综合欧美亚洲 | 亚洲人xxxx| 精品欧美一区二区三区 | av三级网| 色婷婷a | 亚洲香蕉中文网 | 美女隐私黄www网站动漫 | 毛片导航 | 韩国三级与黑人 | 国产精品午夜影院 | 日日躁狠狠躁 | 亚洲精品国产手机 | 国产色频 | 免费人成网站 | 欧美日本国产 | 亚洲午夜剧场 | 邵氏电影《金莲外传2》免费观看 | 日韩久久视频 | 婷婷五月精品中文字幕 | 色片在线免费观看 | 99视频在线观看免费 | 亚洲无限av | 中国毛片基地 | 日韩精品一区二区三区中文字幕 | 午夜寂寞少妇 | 国产啊啊啊啊 | 午夜九九| 2019中文在线观看 | 无码人妻丰满熟妇精品区 | 久久99久久98精品免观看软件 | 精品国产乱子伦 | 麻豆蜜桃91 | 无码人妻精品一区二区 | 精精国产 | 爱情岛论坛自拍亚洲品质极速最新章 | 综合视频一区 | 永久免费av无码网站性色av | 人与动物2免费观看完整版电影高清 | 激情超碰在线 | 精品少妇爆乳无码av无码专区 | 森泽佳奈中文字幕 | 阿v天堂在线 | 玉女心经在线看 | 最近中文字幕免费视频 | 日韩tv| 阿v视频免费在线观看 | 91成人在线看 | 日日摸日日碰夜夜爽无码 | 国产调教在线观看 | 成人app在线 | av在线免费观看网站 | 亚洲欧美日韩在线播放 | 精品国精品国产 | 精品成人av一区二区在线播放 | 激情天天| 天堂二区 | 男女羞羞无遮挡 | 中文字幕av高清 | 精品人妻一区二区三区日产 | 国产在线免费av | 久久无毛| 97久久国产亚洲精品超碰热 | 亚洲久热 | youjizz.com最新| 在线视频在线观看 | 国产精品无码午夜福利 | 99爱免费| 双性人做受视频 | 亚洲黄网站在线观看 | 国产人成在线 | 国产一区二区免费在线 | 99国产超薄肉色丝袜交足 | 欧洲午夜精品 | 女人裸体免费网站 | 午夜有码 | 久久久久成人精品免费播放动漫 | 日本精品人妻无码免费大全 | 国产91熟女高潮一区二区 | 亚洲第一精品网站 | 青青在线播放 | 国产精品麻豆一区二区三区 | 日本aa视频 | 日不卡 |