創作內容

9 GP

C# Socket大檔案傳輸

作者:貓貓風 ฅ●ω●ฅ│2017-06-17 13:50:17│巴幣:18│人氣:8149
.












一般的TCP/IP傳輸都會有2M的限制,主要是因為每個封包的大小有所限制,此篇所使用的方式是基於以上原理,對大檔案傳送的封包進行重組,因此可以接收的檔案大小沒有限制,以下範例會傳輸各種類型的檔案做測試(jpg txt exe mp4),最大的檔案為一百多MB的檔案,接可成功傳輸

Client端 (傳送端


  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ComponentModel;  
  4. using System.Data;  
  5. using System.Drawing;  
  6. using System.Linq;  
  7. using System.Text;  
  8. using System.Windows.Forms;  
  9. using System.Net;  
  10. using System.Net.Sockets;  
  11. using System.IO;  
  12. using System.Threading;  
  13.   
  14. namespace SendFileTest  
  15. {  
  16.     public partial class Form1 : Form  
  17.     {  
  18.         public Form1()  
  19.         {  
  20.             InitializeComponent();  
  21.         }  
  22.   
  23.         private void button1_Click(object sender, EventArgs e)  
  24.         {  
  25.             try   
  26.             {   
  27.                 IPAddress ipAddress = IPAddress.Parse("192.168.1.103");  
  28.                 IPEndPoint ipEnd = new IPEndPoint(ipAddress, 5656);  
  29.                 foreach (string fname in System.IO.Directory.GetFiles("test_folder"))  
  30.                 {  
  31.                     SocketclientSock= new
  32.                     Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.IP);
  33.                     clientSock.Connect(ipEnd);   
  34.                     string fileName = System.Windows.Forms.Application.StartupPath;  
  35.                     //string filePath = "\\test_folder\\test0605.txt";  
  36.                     byte[] fileNameByte = Encoding.ASCII.GetBytes(/*filePath*/"\\"+fname);
  37.                     //將檔案路徑與名稱轉為位元組  
  38.   
  39.                     byte[] fileData = File.ReadAllBytes(fileName + "\\"+fname);  
  40.                     //把指定路徑讀取到的檔案轉成BYTE  
  41.                     byte[] clientData = new byte[4 + fileNameByte.Length + fileData.Length];  
  42.                     byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length);
  43.                     //將檔案路徑與名稱位元組編碼成位元組序列  
  44.   
  45.                     fileNameLen.CopyTo(clientData, 0); //將檔案路徑與名稱加入 clientData  
  46.                     fileNameByte.CopyTo(clientData, 4); //將檔案路徑與名稱加入 clientData  
  47.                     fileData.CopyTo(clientData, 4 + fileNameByte.Length);
  48.                     //將指定路徑讀取到資料寫入clientData  
  49.                     clientSock.Send(clientData); //送出檔案封包  
  50.                     clientSock.Close();   
  51.                     //Thread.Sleep(5000);  
  52.                 }  
  53.             }   
  54.             catch (Exception ex)   
  55.             {   
  56.                 MessageBox.Show("File Sending fail." + ex.Message);   
  57.             }   
  58.         }  
  59.   
  60.         private void button2_Click(object sender, EventArgs e)  
  61.         {  
  62.             //string supportedExtensions = "*.txt,*.jpg,*.exe";  
  63.             int count = 0;  
  64.             string supportedExtensions;  
  65.             supportedExtensions = "*."+textBox1.Text;  
  66.   
  67.             if (textBox1.Text == "")  
  68.             {  
  69.                 //取得資料夾內指定的所有檔案  
  70.                 foreach (string fname in System.IO.Directory.GetFiles("test_folder"))  
  71.                 {  
  72.                     MessageBox.Show(fname);  
  73.                 }  
  74.             }  
  75.             else  
  76.             {  
  77.                 //取得資料夾內指定類型的檔案  
  78.                 foreach (string fname in
  79.                System.IO.Directory.GetFiles("test_folder","*.*",  SearchOption.AllDirectories).
  80.                Where(s =>supportedExtensions.Contains(Path.GetExtension(s).ToLower())))
  81.                 {  
  82.                     count++;  
  83.                     MessageBox.Show(fname);  
  84.                 }  
  85.   
  86.                 if (count == 0)  
  87.                 {  
  88.                     MessageBox.Show("No Match File");  
  89.                 }  
  90.             }  
  91.         }  
  92.     }  
  93. }  

Server端(接收端


  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ComponentModel;  
  4. using System.Data;  
  5. using System.Drawing;  
  6. using System.Linq;  
  7. using System.Text;  
  8. using System.Windows.Forms;  
  9. using System.Net.Sockets;  
  10. using System.Net;  
  11. using System.IO;  
  12. using System.Threading;  
  13. using System.Drawing.Imaging;  
  14.   
  15. namespace FileRecieve  
  16. {  
  17.     public partial class Form1 : Form  
  18.     {  
  19.         Thread _th;  
  20.         private delegate void ChangeUI(Control ctl);  
  21.         private delegate void ChangeUIText(Control ctl, string str);  
  22.   
  23.         public Form1()  
  24.         {  
  25.             InitializeComponent();  
  26.         }  
  27.   
  28.         private void Form1_Load(object sender, EventArgs e)  
  29.         {  
  30.             _th = new Thread(listen_data);  
  31.             _th.Start();  
  32.         }  
  33.   
  34.         private void updateui(Control ctl)  
  35.         {  
  36.             if (ctl.InvokeRequired)  
  37.             {  
  38.                 ChangeUI ui = new ChangeUI(updateui);  
  39.                 ctl.Invoke(ui,ctl);  
  40.             }  
  41.             else  
  42.             {  
  43.                 ctl.Visible = true;  
  44.             }  
  45.         }  
  46.   
  47.         private void updateui2(Control ctl)  
  48.         {  
  49.             if (ctl.InvokeRequired)  
  50.             {  
  51.                 ChangeUI ui = new ChangeUI(updateui2);  
  52.                 ctl.Invoke(ui, ctl);  
  53.             }  
  54.             else  
  55.             {  
  56.                 ctl.Visible = false;  
  57.             }  
  58.         }  
  59.   
  60.         private void updateuiText(Control ctl, string str)  
  61.         {  
  62.             if (ctl.InvokeRequired)  
  63.             {  
  64.                 ChangeUIText ui = new ChangeUIText(updateuiText);  
  65.                 ctl.Invoke(ui, ctl, str);  
  66.             }  
  67.             else  
  68.             {  
  69.                 ctl.Text = str;  
  70.             }  
  71.         }  
  72.   
  73.         private void listen_data()  
  74.         {  
  75.             try  
  76.             {  
  77.                 IPEndPoint ipEnd = new IPEndPoint(IPAddress.Any, 5656);  
  78.                 Socket sock = new Socket(AddressFamily.InterNetwork,
  79.                 SocketType.Stream, ProtocolType.IP);  
  80.                 int receivedBytesLen;  
  81.                 int recieve_data_size;  
  82.                 int fileNameLen;  
  83.                 string fileName;  
  84.                 int count = 0;  
  85.                 sock.Bind(ipEnd);  
  86.                 sock.Listen(10);  
  87.   
  88.                 while (true)  
  89.                 {  
  90.                     int first = 1;  
  91.                     receivedBytesLen = 0;  
  92.                     recieve_data_size = 0;  
  93.                     fileNameLen = 0;  
  94.                     fileName = "";  
  95.                     Socket clientSock = sock.Accept();  
  96.                     byte[] clientData = new byte[1024 * 50000];
  97.                     //5000 = 5MB 50000 = 50MB //定義傳輸每段資料大小,值越大傳越快  
  98.                     //byte[] clientData = new byte[8192];  
  99.                     string receivedPath = System.Windows.Forms.Application.StartupPath;  
  100.                     BinaryWriter bWrite = null;   
  101.                     MemoryStream ms = null;  
  102.                     string file_type = "";  
  103.                     string display_data = "";  
  104.                     string content = "";  
  105.                     double cal_size = 0;  
  106.                        
  107.                     do  
  108.                     {  
  109.                         receivedBytesLen = clientSock.Receive(clientData);
  110.                         //接收資料 (receivedBytesLen = 資料長度)  
  111.   
  112.                         if (first == 1) //第一筆資料為檔名  
  113.                         {  
  114.                             fileNameLen = BitConverter.ToInt32(clientData, 0);
  115.                             //轉換檔名的位元組為整數 (檔名長度)  
  116.                             fileName = Encoding.ASCII.GetString(clientData, 4,fileNameLen);
  117.                             // 1 int = 4 byte  轉換Byte為字串  
  118.                             file_type = fileName.Substring(fileName.Length - 3,3);
  119.                             //取得檔名  
  120.                             //-----------  
  121.                             content = Encoding.ASCII.GetString(clientData, 4 +
  122.                             fileNameLen,     receivedBytesLen - 4 - fileNameLen);
  123.                             //取得檔案內容 起始(檔名以後) 長度(扣除檔名長度)  
  124.                             display_data += content;  
  125.                             //-----------  
  126.                             bWrite = new BinaryWriter(File.Open(receivedPath +
  127.                             fileName,   FileMode.Create));
  128.                              //CREATE 覆蓋舊檔 APPEND 延續舊檔  
  129.                             ms = new MemoryStream();  
  130.                             bWrite.Write(clientData, 4 + fileNameLen, receivedBytesLen - 4 -
  131.                             fileNameLen);
  132.                             //寫入資料 ,跳過起始檔名長度,接收長度減掉檔名長度  
  133.                             ms.Write(clientData, 4 + fileNameLen, receivedBytesLen - 4 -
  134.                             fileNameLen);
  135.                             //寫入資料 ,呈現於BITMAP用  
  136.                         }  
  137.                         else //第二筆接收為資料  
  138.                         {  
  139.                             //-----------  
  140.                             content = Encoding.ASCII.GetString(clientData, 0,
  141.                             receivedBytesLen);  
  142.                             display_data += content;  
  143.                             //-----------  
  144.                             bWrite.Write(clientData/*, 4 + fileNameLen, receivedBytesLen - 4 -
  145.                             fileNameLen*/, 0, receivedBytesLen);
  146.                             //每筆接收起始 0 結束為當次Receive長度  
  147.                             ms.Write(clientData, 0, receivedBytesLen);
  148.                             //寫入資料 ,呈現於BITMAP用  
  149.                         }  
  150.                         recieve_data_size +=receivedBytesLen;
  151.                         //計算資料每筆資料長度並累加,後面可以輸出總值看是否有完整接收  
  152.                         cal_size = recieve_data_size;  
  153.                         cal_size/=1024;  
  154.                         cal_size = Math.Round(cal_size,2);  
  155.                         updateuiText(textBox1, cal_size.ToString());  
  156.                         first++;  
  157.                         Thread.Sleep(10); //每次接收不能太快,否則會資料遺失  
  158.                     }while (clientSock.Available != 0); //如果還沒接收完則繼續接收  
  159.                     //while(receivedBytesLen != 0);  
  160.   
  161.                     updateuiText(textBox2, fileName);  
  162.   
  163.                     if(file_type == "jpg") //如果是圖則呈現在視窗上  
  164.                     {  
  165.                         //pictureBox1.Visible = true;  
  166.                         //richTextBox1.Visible = false;  
  167.                         updateui(pictureBox1);  
  168.                         updateui2(richTextBox1);  
  169.                         Bitmap Img = new Bitmap(ms);  
  170.                         Bitmap imageOut = new Bitmap(Img, 1200, 600);  
  171.                         pictureBox1.Image = imageOut;  
  172.                     }  
  173.                     else  
  174.                     {  
  175.                         //pictureBox1.Visible = false;  
  176.                         //richTextBox1.Visible = true;  
  177.                         updateui(richTextBox1);  
  178.                         updateui2(pictureBox1);  
  179.                         //richTextBox1.Text = display_data;  
  180.                         updateuiText(richTextBox1, display_data);  
  181.                     }  
  182.                     Thread.Sleep(3000);  
  183.                     ms.Close();  
  184.                     count++;  
  185.                     first = 1;  
  186.                     bWrite.Close();  
  187.                     clientSock.Close();  
  188.                 }  
  189.   
  190.             }  
  191.             catch (Exception ex)  
  192.             {  
  193.                 //MessageBox.Show("File Receiving fail." + ex.Message);  
  194.             }   
  195.         }  
  196.     }  
  197. }  

傳輸端資料夾內的檔案



接收端接收到的檔案  下圖為接收後的圖片呈現於畫面上



接收端資料夾 (存放所有從傳送端傳來的檔案



接收端接收文字訊息 ( 內容呈現於畫面上



接收到的文字檔 (確認檔名與資料完全無誤



接收到的圖片檔



接收的影片檔 (確實可放  內容完全正確



傳輸端檔案類型篩選功能  下圖為篩選檔名為JPG的檔案



引用網址:https://home.gamer.com.tw/TrackBack.php?sn=3612377
All rights reserved. 版權所有,保留一切權利

相關創作

同標籤作品搜尋:涼涼風|C#

留言共 4 篇留言

小刀
很棒的說~

06-17 21:23

貓貓風 ฅ●ω●ฅ
謝謝刀姊唷

06-17 21:29

Kie5843
不好意思請問一下 如果我傳送的資料夾是需要指定路徑的 請問該怎麼做 因為我試過您的程式碼 發現要傳送的資料夾都是綁在跟EXE同在的資料夾裡 如果我要把傳送資料夾的路徑寫死的話 請問怎麼做呢

04-10 15:31

貓貓風 ฅ●ω●ฅ
改這邊 string receivedPath = System.Windows.Forms.Application.StartupPath; 09-14 09:37
貓貓風 ฅ●ω●ฅ
receivedPath 改成你的路徑09-14 09:38
James64
大大你好,不知道你有沒有使用過Socket.BeginSend,想嘗試發送超過64KB位元組的資料,給Web但是每次只要一發,我跟Web間的Socket就斷了,不知道有沒有什麼解法

05-26 19:00

貓貓風 ฅ●ω●ฅ
Sorry,I have never use the function of Socket.BeginSend .05-26 23:08
我要留言提醒:您尚未登入,請先登入再留言

9喜歡★s1234567 可決定是否刪除您的留言,請勿發表違反站規文字。

前一篇:C# 委派(delega... 後一篇:arduino 四位數七...

追蹤私訊切換新版閱覽

作品資料夾

Waterfall10絕大部份巴友
分享網路小說《全職藝術家》,作者:我最白,歡迎瀏覽 ~看更多我要大聲說昨天22:21


face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】