欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C# Socket文件上傳至服務(wù)器的操作方法

 更新時(shí)間:2024年05月24日 11:31:12   作者:不自由的小碼  
文件上傳有FTP、WebApi、WebService等等,這次我們來實(shí)現(xiàn)一個(gè)基于socket通信的本地客戶端上傳文件到服務(wù)器的例子,這篇文章主要介紹了C# Socket文件上傳至服務(wù)器的操作方法,需要的朋友可以參考下

前言

文件上傳有FTP、WebApi、WebService等等,這次我們來實(shí)現(xiàn)一個(gè)基于socket通信的本地客戶端上傳文件到服務(wù)器的例子。

運(yùn)行效果

一、Socket(套接字)概念

說起socket通信,那就不得不介紹一下套接字(socket),套接字是通信的基石,是支持TCP/IP協(xié)議的網(wǎng)絡(luò)通信的基本操作單元,套接字Socket=(IP地址:端口號)。就是對網(wǎng)絡(luò)中不同主機(jī)上的應(yīng)用進(jìn)程之間進(jìn)行雙向通信的端點(diǎn)的抽象。一個(gè)套接字就是網(wǎng)絡(luò)上進(jìn)程通信的一端,提供了應(yīng)用層進(jìn)程利用網(wǎng)絡(luò)協(xié)議交換數(shù)據(jù)的機(jī)制。從所處的地位來講,套接字上聯(lián)應(yīng)用進(jìn)程,下聯(lián)網(wǎng)絡(luò)協(xié)議棧,是應(yīng)用程序通過網(wǎng)絡(luò)協(xié)議進(jìn)行通信的接口,是應(yīng)用程序與網(wǎng)絡(luò)協(xié)議棧進(jìn)行交互的接口,它包含進(jìn)行網(wǎng)絡(luò)通信必須的五種信息:連接使用的協(xié)議,本地主機(jī)的IP地址,本地進(jìn)程的協(xié)議端口,遠(yuǎn)地主機(jī)的IP地址,遠(yuǎn)地進(jìn)程的協(xié)議端口。

二、Socket通信的建立

建立Socket連接至少需要一對套接字,其中一個(gè)運(yùn)行于客戶端,稱為ClientSocket ,另一個(gè)運(yùn)行于服務(wù)器端,稱為ServerSocket 。

三、通信流程

根據(jù)連接啟動的方式以及本地套接字要連接的目標(biāo),套接字之間的連接過程可以分為三個(gè)步驟:
(1)服務(wù)器監(jiān)聽。
(2)客戶端請求。
(3)連接確認(rèn)。
1.服務(wù)器監(jiān)聽
所謂服務(wù)器監(jiān)聽,是指服務(wù)器端套接字并不定位具體的客戶端套接字,而是處于等待連接的狀態(tài),實(shí)時(shí)監(jiān)控網(wǎng)絡(luò)狀態(tài)。
2.客戶端請求
所謂客戶端請求,是指由客戶端的套接字提出連接請求,要連接的目標(biāo)是服務(wù)器端的套接字。為此,客戶端的套接字必須首先描述它要連接的服務(wù)器的套接字,指出服務(wù)器端套接字的地址和端口號,然后就向服務(wù)器端接字提出連接請求 。
3.連接確認(rèn)
所謂連接確認(rèn),是指當(dāng)服務(wù)器端套接字監(jiān)聽到或者說接收到客戶端套接字的連接請求,就會響應(yīng)客戶端套接字的請求,建立一個(gè)新的線程,并把服務(wù)器端套接字的描述發(fā)送給客戶端。一旦客戶端確認(rèn)了此描述,連接就建立好了。而服務(wù)器端套接字繼續(xù)處于監(jiān)聽狀態(tài),接收其他客戶端套接字的連接請求。

四、實(shí)現(xiàn)

1.ClientSocket

在這里插入圖片描述

本機(jī)IP地址在窗體加載的時(shí)候賦值。

     private void FrmMain_Load(object sender, EventArgs e)
     {
       //獲得本機(jī)的IP地址   
       this.textBox4.Text = Dns.GetHostByName(Dns.GetHostName()).AddressList[0].ToString();
      }

接下來我們正式開始,點(diǎn)擊瀏覽,選擇需要上傳的文件。此時(shí)我們獲取當(dāng)前文件的全路徑、文件名稱及合計(jì)字節(jié)。

        /// <summary>
        /// 瀏覽
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            //選擇要進(jìn)行傳輸?shù)奈募?  
            if (this.openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                FileInfo EzoneFile = new FileInfo(this.openFileDialog1.FileName);
                this.textBox1.Text = EzoneFile.FullName;
                this.textBox2.Text = EzoneFile.Name;
                this.textBox3.Text = EzoneFile.Length.ToString();
            }
        }

點(diǎn)擊發(fā)送按鈕,將文件以字節(jié)流的形式發(fā)送到服務(wù)器端,此時(shí)應(yīng)該單獨(dú)開一個(gè)子線程以保證監(jiān)聽運(yùn)行,監(jiān)聽事件定義StartSend。

        /// <summary>
        /// 開始發(fā)送
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            //開啟文件傳輸子線程   
            Thread TempThread = new Thread(new ThreadStart(this.StartSend));
            TempThread.Start();
        }

StartSend事件中,根據(jù)文件路徑創(chuàng)建一個(gè)文件對象,配置操作流、創(chuàng)建連接對象、IP\Port等等關(guān)鍵信息。首先我們來創(chuàng)建一個(gè)幫助類FileClientSocket.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
namespace TouchSocketClient
{
    public class FileClientSocket
    {
        public static int SendData(Socket s, byte[] data)
        {
            int total = 0;
            int size = data.Length;
            int dataleft = size;
            int sent;
            while (total < size)
            {
                sent = s.Send(data, total, dataleft, SocketFlags.None);
                total += sent;
                dataleft -= sent;
            }
            return total;
        }
        public static byte[] ReceiveData(Socket s, int size)
        {
            int total = 0;
            int dataleft = size;
            byte[] data = new byte[size];
            int recv;
            while (total < size)
            {
                recv = s.Receive(data, total, dataleft, SocketFlags.None);
                if (recv == 0)
                {
                    data = null;
                    break;
                }
                total += recv;
                dataleft -= recv;
            }
            return data;
        }
        public static int SendVarData(Socket s, byte[] data)
        {
            int total = 0;
            int size = data.Length;
            int dataleft = size;
            int sent;
            byte[] datasize = new byte[4];
            datasize = BitConverter.GetBytes(size);
            sent = s.Send(datasize);
            while (total < size)
            {
                sent = s.Send(data, total, dataleft, SocketFlags.None);
                total += sent;
                dataleft -= sent;
            }
            return total;
        }
        public static byte[] ReceiveVarData(Socket s)
        {
            int total = 0;
            int recv;
            byte[] datasize = new byte[4];
            recv = s.Receive(datasize, 0, 4, SocketFlags.None);
            int size = BitConverter.ToInt32(datasize, 0);
            int dataleft = size;
            byte[] data = new byte[size];
            while (total < size)
            {
                recv = s.Receive(data, total, dataleft, SocketFlags.None);
                if (recv == 0)
                {
                    data = null;
                    break;
                }
                total += recv;
                dataleft -= recv;
            }
            return data;
        }
    }
}

StartSend方法實(shí)現(xiàn)

        private void StartSend()
        {
            //創(chuàng)建一個(gè)文件對象   
            FileInfo EzoneFile = new FileInfo(this.textBox1.Text);
            //打開文件流   
            FileStream EzoneStream = EzoneFile.OpenRead();
            //包的大小   
            int PacketSize = int.Parse(this.textBox6.Text);
            //包的數(shù)量   
            int PacketCount = (int)(EzoneStream.Length / ((long)PacketSize));
            //最后一個(gè)包的大小   
            int LastDataPacket = (int)(EzoneStream.Length - ((long)(PacketSize * PacketCount)));
            //指向遠(yuǎn)程服務(wù)端節(jié)點(diǎn)   
            IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(txtIP.Text.Trim()), int.Parse(this.textBox5.Text));
            //創(chuàng)建套接字   
            Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //連接到發(fā)送端   
            client.Connect(ipep);
            //獲得客戶端節(jié)點(diǎn)對象   
            IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;
            //獲得客戶端的IP地址   
            //this.textBox7.Text=clientep.Address.ToString();   
            //發(fā)送[文件名]到客戶端   
            FileClientSocket.SendVarData(client,System.Text.Encoding.Unicode.GetBytes(EzoneFile.Name));
            //發(fā)送[包的大小]到客戶端   
            FileClientSocket.SendVarData(client,System.Text.Encoding.Unicode.GetBytes(PacketSize.ToString()));
            //發(fā)送[包的總數(shù)量]到客戶端   
            FileClientSocket.SendVarData(client,System.Text.Encoding.Unicode.GetBytes(PacketCount.ToString()));
            //發(fā)送[最后一個(gè)包的大小]到客戶端   
            FileClientSocket.SendVarData(client,System.Text.Encoding.Unicode.GetBytes(LastDataPacket.ToString()));
            //數(shù)據(jù)包   
            byte[] data = new byte[PacketSize];
            //開始循環(huán)發(fā)送數(shù)據(jù)包   
            for (int i = 0; i < PacketCount; i++)
            {
                //從文件流讀取數(shù)據(jù)并填充數(shù)據(jù)包   
                EzoneStream.Read(data, 0, data.Length);
                //發(fā)送數(shù)據(jù)包   
                FileClientSocket.SendVarData(client, data);
            }
            //如果還有多余的數(shù)據(jù)包,則應(yīng)該發(fā)送完畢!   
            if (LastDataPacket != 0)
            {
                data = new byte[LastDataPacket];
                EzoneStream.Read(data, 0, data.Length);
                FileClientSocket.SendVarData(client, data);
            }
            //關(guān)閉套接字   
            client.Close();  
            //關(guān)閉文件流   
            EzoneStream.Close();
            MessageBox.Show("文件傳輸完畢!");
        }

至此客戶端部分已經(jīng)完成,下面開始實(shí)現(xiàn)服務(wù)端。

2.ServerSocket

我們新建一個(gè)控制臺應(yīng)用程序,TouchSocketServer。

在這里插入圖片描述

在Main方法中 注冊接收事件,并開始子線程進(jìn)行處理。

static void Main(string[] args)
        {
            //開啟接收線程   
            Thread TempThread = new Thread(new ThreadStart(StartReceive));
            TempThread.Start();
        }

同樣我們服務(wù)端也需要一個(gè)Server類(FileSocketServer.cs)

namespace TouchSocketServer
{
    public class FileSocketServer
    {
        public static int SendData(Socket s, byte[] data)
        {
            int total = 0;
            int size = data.Length;
            int dataleft = size;
            int sent;
            while (total < size)
            {
                sent = s.Send(data, total, dataleft, SocketFlags.None);
                total += sent;
                dataleft -= sent;
            }
            return total;
        }
        public static byte[] ReceiveData(Socket s, int size)
        {
            int total = 0;
            int dataleft = size;
            byte[] data = new byte[size];
            int recv;
            while (total < size)
            {
                recv = s.Receive(data, total, dataleft, SocketFlags.None);
                if (recv == 0)
                {
                    data = null;
                    break;
                }
                total += recv;
                dataleft -= recv;
            }
            return data;
        }
        public static int SendVarData(Socket s, byte[] data)
        {
            int total = 0;
            int size = data.Length;
            int dataleft = size;
            int sent;
            byte[] datasize = new byte[4];
            datasize = BitConverter.GetBytes(size);
            sent = s.Send(datasize);
            while (total < size)
            {
                sent = s.Send(data, total, dataleft, SocketFlags.None);
                total += sent;
                dataleft -= sent;
            }
            return total;
        }
        public static byte[] ReceiveVarData(Socket s)
        {
            int total = 0;
            int recv;
            byte[] datasize = new byte[4];
            recv = s.Receive(datasize, 0, 4, SocketFlags.None);
            int size = BitConverter.ToInt32(datasize, 0);
            int dataleft = size;
            byte[] data = new byte[size];
            while (total < size)
            {
                recv = s.Receive(data, total, dataleft, SocketFlags.None);
                if (recv == 0)
                {
                    data = null;
                    break;
                }
                total += recv;
                dataleft -= recv;
            }
            return data;
        }
    }
}

接收函數(shù)

private static void StartReceive()
        {
            //創(chuàng)建一個(gè)網(wǎng)絡(luò)端點(diǎn)
            Console.ForegroundColor = ConsoleColor.DarkRed;
            Console.WriteLine($"{DateTime.Now} [初始化網(wǎng)絡(luò)端點(diǎn)]");
            IPEndPoint ipep = new IPEndPoint(IPAddress.Any, int.Parse("1005"));
            //MessageBox.Show(IPAddress.Any);   
            //創(chuàng)建一個(gè)套接字   
            Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //綁定套接字到端口   
            server.Bind(ipep);
            //開始偵聽(并堵塞該線程)   
            Console.WriteLine($"{DateTime.Now} [開始偵聽并堵塞該線程]");
            server.Listen(10);
            while (true)
            {
                try
                {
                    Socket client = server.Accept();
                    ClientSocket = client;
                    Thread TempThread = new Thread(new ThreadStart(Create));
                    TempThread.Start();
                }
                catch (Exception ex)
                {
                    int k = 0;
                }
            }
        }

創(chuàng)建文件函數(shù)

public static void Create()
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine($"{DateTime.Now} [創(chuàng)建對象]");
            Socket client = ClientSocket;
            //確認(rèn)連接   
            //Socket client = server.Accept();
            //獲得客戶端節(jié)點(diǎn)對象   
            Console.ForegroundColor = ConsoleColor.Yellow;
            IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;
            Console.WriteLine($"{DateTime.Now} 請求對象:[{clientep.Address}]");
            //獲得[文件名]   
            string SendFileName = System.Text.Encoding.Unicode.GetString(FileSocketServer.ReceiveVarData(client));
            Console.WriteLine($"{DateTime.Now} 文件名稱:[{SendFileName}]");
            //獲得[包的大小]   
            string bagSize = System.Text.Encoding.Unicode.GetString(FileSocketServer.ReceiveVarData(client));
            //獲得[包的總數(shù)量]   
            int bagCount = int.Parse(System.Text.Encoding.Unicode.GetString(FileSocketServer.ReceiveVarData(client)));
            //獲得[最后一個(gè)包的大小]   
            string bagLast = System.Text.Encoding.Unicode.GetString(FileSocketServer.ReceiveVarData(client));
            //自動創(chuàng)建文件夾
            string path = $@"{System.AppDomain.CurrentDomain.BaseDirectory}\Log\{clientep.Address}({DateTime.Now.ToString("yyyyMMddhhmmssffffff")})";
            Directory.CreateDirectory(path);
            //創(chuàng)建一個(gè)新文件   
            FileStream MyFileStream = new FileStream($@"{path}\" + SendFileName, FileMode.Create, FileAccess.Write);
            Console.WriteLine($"{DateTime.Now} 創(chuàng)建目標(biāo):[已創(chuàng)建]");
            //已發(fā)送包的個(gè)數(shù)   
            int SendedCount = 0;
            while (true)
            {
                byte[] data = FileSocketServer.ReceiveVarData(client);
                if (data.Length == 0)
                {
                    break;
                }
                else
                {
                    SendedCount++;
                    //將接收到的數(shù)據(jù)包寫入到文件流對象   
                    MyFileStream.Write(data, 0, data.Length);
                    //顯示已發(fā)送包的個(gè)數(shù)
                }
            }
            //關(guān)閉文件流   
            MyFileStream.Close();
            //關(guān)閉套接字   
            client.Close();
            Console.WriteLine($"{DateTime.Now} 傳輸結(jié)果:[成功]");
        }

到此這篇關(guān)于C# Socket文件上傳至服務(wù)器的文章就介紹到這了,更多相關(guān)C# Socket文件上傳內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 利用C#編寫一個(gè)Windows服務(wù)程序的方法詳解

    利用C#編寫一個(gè)Windows服務(wù)程序的方法詳解

    這篇文章主要為大家詳細(xì)介紹了如何利用C#編寫一個(gè)Windows服務(wù)程序,文中的實(shí)現(xiàn)方法講解詳細(xì),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-03-03
  • 詳細(xì)了解C# 枚舉與位枚舉

    詳細(xì)了解C# 枚舉與位枚舉

    這篇文章主要介紹了C# 枚舉與位枚舉的相關(guān)資料,文中講解非常細(xì)致,幫助大家更好的理解和學(xué)習(xí)枚舉和位枚舉,感興趣的朋友可以了解下
    2020-07-07
  • C#中TreeView實(shí)現(xiàn)適合兩級節(jié)點(diǎn)的選中節(jié)點(diǎn)方法

    C#中TreeView實(shí)現(xiàn)適合兩級節(jié)點(diǎn)的選中節(jié)點(diǎn)方法

    這篇文章主要介紹了C#中TreeView實(shí)現(xiàn)適合兩級節(jié)點(diǎn)的選中節(jié)點(diǎn)方法,實(shí)例分析了C#中TreeView節(jié)點(diǎn)操作的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-09-09
  • C#利用GDI繪制常見圖形和文字

    C#利用GDI繪制常見圖形和文字

    本文主要介紹了C#中利用GDI來繪制圖形和文字的方法,并提供的簡單的示例供大家參考學(xué)習(xí),希望能夠?qū)Υ蠹矣兴鶐椭?/div> 2016-03-03
  • 詳細(xì)介紹C# 泛型

    詳細(xì)介紹C# 泛型

    這篇文章主要介紹了C# 泛型的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)C#,感興趣的朋友可以了解下
    2020-08-08
  • c# 模擬線性回歸的示例

    c# 模擬線性回歸的示例

    這篇文章主要介紹了c# 模擬線性回歸的示例,幫助大家利用c#進(jìn)行機(jī)器學(xué)習(xí),感興趣的朋友可以了解下
    2020-10-10
  • C#實(shí)現(xiàn)AddRange為數(shù)組添加多個(gè)元素的方法

    C#實(shí)現(xiàn)AddRange為數(shù)組添加多個(gè)元素的方法

    這篇文章主要介紹了C#實(shí)現(xiàn)AddRange為數(shù)組添加多個(gè)元素的方法,實(shí)例分析了AddRange方法的使用技巧,需要的朋友可以參考下
    2015-06-06
  • c#讀取excel方法實(shí)例分析

    c#讀取excel方法實(shí)例分析

    這篇文章主要介紹了c#讀取excel方法,實(shí)例分析了C#讀取excel文件的原理與相關(guān)技巧,需要的朋友可以參考下
    2015-06-06
  • C#嵌套類的訪問方法

    C#嵌套類的訪問方法

    這篇文章主要介紹了C#嵌套類的訪問方法,本文給出了嵌套類代碼和訪問方法代碼,不會的同學(xué)照搬對照中的方法即可,需要的朋友可以參考下
    2015-04-04
  • C#實(shí)現(xiàn)PDF合并的項(xiàng)目實(shí)踐

    C#實(shí)現(xiàn)PDF合并的項(xiàng)目實(shí)踐

    有時(shí)我們可能會遇到需要的資料或教程被分成了幾部分存放在多個(gè)PDF文件中,本文主要介紹了C#實(shí)現(xiàn)PDF合并的項(xiàng)目實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01

最新評論