1. 程式人生 > >C#.網路程式設計 Socket基礎(三) 基於WinForm系統Socket TCP協議 實現端到端(伺服器與客戶端).txt.word.png等不同型別檔案傳輸

C#.網路程式設計 Socket基礎(三) 基於WinForm系統Socket TCP協議 實現端到端(伺服器與客戶端).txt.word.png等不同型別檔案傳輸

一、簡介:

前面的兩篇介紹了字串傳輸、圖片傳輸:

其實,本文針對Socket基礎(二)進一步完成,以便可以進行多種檔案傳輸。

二、基於不同的流(檔案流、記憶體流、網路等)讀寫。

1、圖片傳輸

方法一:(在客戶端用檔案流傳送(即將圖片寫到檔案流去,以便傳送),在服務端用記憶體流來接收(即從記憶體流讀取圖片出來))

方法二:(在客戶端用檔案流傳送(即將圖片寫到檔案流去,以便傳送),在服務端也用檔案流來接收(即從檔案流讀取圖片出來))

服務端程式碼:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SocketServer_SendImage
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        //Form1_Load表示預設的載入,相當於初始化。
        private void Form1_Load(object sender, EventArgs e)
        {
            lab_pro.Text = "接收:0/100";
            //button1.Text = "BBBBB";
        }
        /// <summary>
        /// 開啟服務
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            button1.Text = "監聽中...";
            button1.Enabled = false;
            Socket receiveSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint hostIpEndPoint = new IPEndPoint(IPAddress.Parse("1.1.1.2"), 8888);

            //設定接收資料緩衝區的大小
            byte[] b = new byte[4096];
            receiveSocket.Bind(hostIpEndPoint);
            //監聽
            receiveSocket.Listen(2);
            //接受客戶端連線
            Socket hostSocket = receiveSocket.Accept();
            //記憶體流fs的初始容量大小為0,隨著資料增長而擴充套件。
            //MemoryStream fs = new MemoryStream();
            string Path = "C:\\Users\\lanmage2\\Desktop\\AA";
            FileStream fs = new FileStream(Path + "\\新圖片.png", FileMode.Create, FileAccess.Write);
            int length = 0;
            //每接受一次,只能讀取小於等於緩衝區的大小4096個位元組
            while ((length = hostSocket.Receive(b)) > 0)
            {
                //將接受到的資料b,按長度length放到記憶體流中。
                fs.Write(b, 0, length);

                if (progressBar1.Value < 100)
                {
                    //進度條的預設值為0
                    progressBar1.Value++;
                    lab_pro.Text = "接收:" + progressBar1.Value + "/100";
                }
            }
            progressBar1.Value = 100;
            lab_pro.Text = "接收:" + progressBar1.Value + "/100";
            fs.Flush();
            /*Bitmap類,可以將*/
            //Bitmap Img = new Bitmap(fs);
            //Img.Save(@"reveive.jpg", ImageFormat.Png);
            //關閉寫檔案流
            fs.Close();
            //關閉接收資料的Socket
            hostSocket.Shutdown(SocketShutdown.Receive);
            hostSocket.Close();
            //關閉傳送連線
            receiveSocket.Close();
        }
    }
}

2、傳輸文件(比如.txt文件或其他)

方法一:

服務端大部分程式碼參考 1、圖片傳輸  方法二   的程式碼,但是其改動了截圖部分

方法2:

在客戶端用檔案流傳送(即將圖片寫到檔案流去,以便傳送),在服務端用記憶體流來快取,並用檔案流來輸出,這種方法是最理想的,既可以傳圖片,可以傳其他任意檔案:

伺服器端:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SocketServer_SendImage
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        //Form1_Load表示預設的載入,相當於初始化。
        private void Form1_Load(object sender, EventArgs e)
        {
            lab_pro.Text = "接收:0/100";
            //button1.Text = "BBBBB";
        }
        /// <summary>
        /// 開啟服務
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            button1.Text = "監聽中...";
            button1.Enabled = false;
            Socket receiveSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint hostIpEndPoint = new IPEndPoint(IPAddress.Parse("1.1.1.2"), 8888);

            //設定接收資料緩衝區的大小
            byte[] b = new byte[4096];
            receiveSocket.Bind(hostIpEndPoint);
            //監聽
            receiveSocket.Listen(2);
            //接受客戶端連線
            Socket hostSocket = receiveSocket.Accept();
            //記憶體流fs的初始容量大小為0,隨著資料增長而擴充套件。
            MemoryStream fs = new MemoryStream();
            //string Path = "C:\\Users\\lanmage2\\Desktop\\AA";
            //FileStream fs = new FileStream(Path, FileMode.Open);
            int length = 0;
            //每接受一次,只能讀取小於等於緩衝區的大小4096個位元組
            while ((length = hostSocket.Receive(b)) > 0)
            {
                //將接受到的資料b,按長度length放到記憶體流中。
                fs.Write(b, 0, length);

                if (progressBar1.Value < 100)
                {
                    //進度條的預設值為0
                    progressBar1.Value++;
                    lab_pro.Text = "接收:" + progressBar1.Value + "/100";
                }
            }
            progressBar1.Value = 100;
            lab_pro.Text = "接收:" + progressBar1.Value + "/100";
            fs.Flush();
 
            fs.Seek(0, SeekOrigin.Begin);
            byte[] byteArray = new byte[fs.Length];
            int count = 0;
            while (count < fs.Length)
            {
                byteArray[count] = Convert.ToByte(fs.ReadByte());
                count++;
            }
            string Path = "C:\\Users\\lanmage2\\Desktop\\AA";
            //FileStream filestream = new FileStream(Path + "\\檔案1.txt", FileMode.OpenOrCreate);
            FileStream filestream  = File.Create(Path);
            //filestream.Write(byteArray, 0, byteArray.Length);//不能用
            //System.IO.File.WriteAllBytes(Path, byteArray);//能用
         
            /*Bitmap類,可以將*/
            //Bitmap Img = new Bitmap(fs);
            //Img.Save(@"reveive.jpg", ImageFormat.Png);
            //關閉寫檔案流
            fs.Close();
            //關閉接收資料的Socket
            hostSocket.Shutdown(SocketShutdown.Receive);
            hostSocket.Close();
            //關閉傳送連線
            receiveSocket.Close();
        }
    }
}

三、總結

本文隨意可以傳輸不同型別的檔案,但是沒辦法動態識別不同的檔案型別,不夠靈活。在我下一篇文章,將根據使用者端傳送的資訊,將對不同的檔案型別進行動態的識別。