.
一般的TCP/IP傳輸都會有2M的限制,主要是因為每個封包的大小有所限制,此篇所使用的方式是基於以上原理,對大檔案傳送的封包進行重組,因此可以接收的檔案大小沒有限制,以下範例會傳輸各種類型的檔案做測試(jpg txt exe mp4),最大的檔案為一百多MB的檔案,接可成功傳輸
Client端 (傳送端
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Windows.Forms;
- using System.Net;
- using System.Net.Sockets;
- using System.IO;
- using System.Threading;
-
- namespace SendFileTest
- {
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
-
- private void button1_Click(object sender, EventArgs e)
- {
- try
- {
- IPAddress ipAddress = IPAddress.Parse("192.168.1.103");
- IPEndPoint ipEnd = new IPEndPoint(ipAddress, 5656);
- foreach (string fname in System.IO.Directory.GetFiles("test_folder"))
- {
- SocketclientSock= new
- Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.IP);
- clientSock.Connect(ipEnd);
- string fileName = System.Windows.Forms.Application.StartupPath;
- //string filePath = "\\test_folder\\test0605.txt";
- byte[] fileNameByte = Encoding.ASCII.GetBytes(/*filePath*/"\\"+fname);
- //將檔案路徑與名稱轉為位元組
-
- byte[] fileData = File.ReadAllBytes(fileName + "\\"+fname);
- //把指定路徑讀取到的檔案轉成BYTE
- byte[] clientData = new byte[4 + fileNameByte.Length + fileData.Length];
- byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length);
- //將檔案路徑與名稱位元組編碼成位元組序列
-
- fileNameLen.CopyTo(clientData, 0); //將檔案路徑與名稱加入 clientData
- fileNameByte.CopyTo(clientData, 4); //將檔案路徑與名稱加入 clientData
- fileData.CopyTo(clientData, 4 + fileNameByte.Length);
- //將指定路徑讀取到資料寫入clientData
- clientSock.Send(clientData); //送出檔案封包
- clientSock.Close();
- //Thread.Sleep(5000);
- }
- }
- catch (Exception ex)
- {
- MessageBox.Show("File Sending fail." + ex.Message);
- }
- }
-
- private void button2_Click(object sender, EventArgs e)
- {
- //string supportedExtensions = "*.txt,*.jpg,*.exe";
- int count = 0;
- string supportedExtensions;
- supportedExtensions = "*."+textBox1.Text;
-
- if (textBox1.Text == "")
- {
- //取得資料夾內指定的所有檔案
- foreach (string fname in System.IO.Directory.GetFiles("test_folder"))
- {
- MessageBox.Show(fname);
- }
- }
- else
- {
- //取得資料夾內指定類型的檔案
- foreach (string fname in
- System.IO.Directory.GetFiles("test_folder","*.*", SearchOption.AllDirectories).
- Where(s =>supportedExtensions.Contains(Path.GetExtension(s).ToLower())))
- {
- count++;
- MessageBox.Show(fname);
- }
-
- if (count == 0)
- {
- MessageBox.Show("No Match File");
- }
- }
- }
- }
- }
Server端(接收端
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Windows.Forms;
- using System.Net.Sockets;
- using System.Net;
- using System.IO;
- using System.Threading;
- using System.Drawing.Imaging;
-
- namespace FileRecieve
- {
- public partial class Form1 : Form
- {
- Thread _th;
- private delegate void ChangeUI(Control ctl);
- private delegate void ChangeUIText(Control ctl, string str);
-
- public Form1()
- {
- InitializeComponent();
- }
-
- private void Form1_Load(object sender, EventArgs e)
- {
- _th = new Thread(listen_data);
- _th.Start();
- }
-
- private void updateui(Control ctl)
- {
- if (ctl.InvokeRequired)
- {
- ChangeUI ui = new ChangeUI(updateui);
- ctl.Invoke(ui,ctl);
- }
- else
- {
- ctl.Visible = true;
- }
- }
-
- private void updateui2(Control ctl)
- {
- if (ctl.InvokeRequired)
- {
- ChangeUI ui = new ChangeUI(updateui2);
- ctl.Invoke(ui, ctl);
- }
- else
- {
- ctl.Visible = false;
- }
- }
-
- private void updateuiText(Control ctl, string str)
- {
- if (ctl.InvokeRequired)
- {
- ChangeUIText ui = new ChangeUIText(updateuiText);
- ctl.Invoke(ui, ctl, str);
- }
- else
- {
- ctl.Text = str;
- }
- }
-
- private void listen_data()
- {
- try
- {
- IPEndPoint ipEnd = new IPEndPoint(IPAddress.Any, 5656);
- Socket sock = new Socket(AddressFamily.InterNetwork,
- SocketType.Stream, ProtocolType.IP);
- int receivedBytesLen;
- int recieve_data_size;
- int fileNameLen;
- string fileName;
- int count = 0;
- sock.Bind(ipEnd);
- sock.Listen(10);
-
- while (true)
- {
- int first = 1;
- receivedBytesLen = 0;
- recieve_data_size = 0;
- fileNameLen = 0;
- fileName = "";
- Socket clientSock = sock.Accept();
- byte[] clientData = new byte[1024 * 50000];
- //5000 = 5MB 50000 = 50MB //定義傳輸每段資料大小,值越大傳越快
- //byte[] clientData = new byte[8192];
- string receivedPath = System.Windows.Forms.Application.StartupPath;
- BinaryWriter bWrite = null;
- MemoryStream ms = null;
- string file_type = "";
- string display_data = "";
- string content = "";
- double cal_size = 0;
-
- do
- {
- receivedBytesLen = clientSock.Receive(clientData);
- //接收資料 (receivedBytesLen = 資料長度)
-
- if (first == 1) //第一筆資料為檔名
- {
- fileNameLen = BitConverter.ToInt32(clientData, 0);
- //轉換檔名的位元組為整數 (檔名長度)
- fileName = Encoding.ASCII.GetString(clientData, 4,fileNameLen);
- // 1 int = 4 byte 轉換Byte為字串
- file_type = fileName.Substring(fileName.Length - 3,3);
- //取得檔名
- //-----------
- content = Encoding.ASCII.GetString(clientData, 4 +
- fileNameLen, receivedBytesLen - 4 - fileNameLen);
- //取得檔案內容 起始(檔名以後) 長度(扣除檔名長度)
- display_data += content;
- //-----------
- bWrite = new BinaryWriter(File.Open(receivedPath +
- fileName, FileMode.Create));
- //CREATE 覆蓋舊檔 APPEND 延續舊檔
- ms = new MemoryStream();
- bWrite.Write(clientData, 4 + fileNameLen, receivedBytesLen - 4 -
- fileNameLen);
- //寫入資料 ,跳過起始檔名長度,接收長度減掉檔名長度
- ms.Write(clientData, 4 + fileNameLen, receivedBytesLen - 4 -
- fileNameLen);
- //寫入資料 ,呈現於BITMAP用
- }
- else //第二筆接收為資料
- {
- //-----------
- content = Encoding.ASCII.GetString(clientData, 0,
- receivedBytesLen);
- display_data += content;
- //-----------
- bWrite.Write(clientData/*, 4 + fileNameLen, receivedBytesLen - 4 -
- fileNameLen*/, 0, receivedBytesLen);
- //每筆接收起始 0 結束為當次Receive長度
- ms.Write(clientData, 0, receivedBytesLen);
- //寫入資料 ,呈現於BITMAP用
- }
- recieve_data_size +=receivedBytesLen;
- //計算資料每筆資料長度並累加,後面可以輸出總值看是否有完整接收
- cal_size = recieve_data_size;
- cal_size/=1024;
- cal_size = Math.Round(cal_size,2);
- updateuiText(textBox1, cal_size.ToString());
- first++;
- Thread.Sleep(10); //每次接收不能太快,否則會資料遺失
- }while (clientSock.Available != 0); //如果還沒接收完則繼續接收
- //while(receivedBytesLen != 0);
-
- updateuiText(textBox2, fileName);
-
- if(file_type == "jpg") //如果是圖則呈現在視窗上
- {
- //pictureBox1.Visible = true;
- //richTextBox1.Visible = false;
- updateui(pictureBox1);
- updateui2(richTextBox1);
- Bitmap Img = new Bitmap(ms);
- Bitmap imageOut = new Bitmap(Img, 1200, 600);
- pictureBox1.Image = imageOut;
- }
- else
- {
- //pictureBox1.Visible = false;
- //richTextBox1.Visible = true;
- updateui(richTextBox1);
- updateui2(pictureBox1);
- //richTextBox1.Text = display_data;
- updateuiText(richTextBox1, display_data);
- }
- Thread.Sleep(3000);
- ms.Close();
- count++;
- first = 1;
- bWrite.Close();
- clientSock.Close();
- }
-
- }
- catch (Exception ex)
- {
- //MessageBox.Show("File Receiving fail." + ex.Message);
- }
- }
- }
- }
傳輸端資料夾內的檔案
接收端接收到的檔案 下圖為接收後的圖片呈現於畫面上
接收端資料夾 (存放所有從傳送端傳來的檔案
接收端接收文字訊息 ( 內容呈現於畫面上
接收到的文字檔 (確認檔名與資料完全無誤
接收到的圖片檔
接收的影片檔 (確實可放 內容完全正確
傳輸端檔案類型篩選功能 下圖為篩選檔名為JPG的檔案