假設我們需要實現一個基于網絡的文件上傳系統,用戶可以通過客戶端將本地文件上傳到服務端。這種情況經常出現在文件存儲和共享、云存儲等應用場景中。使用Socket編程可以實現高效可靠的文件傳輸。
基于以上需求,我們可以使用C#的Socket編程實現一個文件上傳系統,包括客戶端和服務端的程序。在程序中使用Socket進行網絡連接和數據傳輸,同時對連接錯誤和文件錯誤進行適當處理和異常捕獲。
dotnet new wpf -n "FileUploaderClient"
MainWindow.xaml:
<Window x:Class="FileUploaderClient.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="文件上傳客戶端" Height="350" Width="500"> <Grid> <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBlock Text="選擇要上傳的文件:" Margin="0 0 0 10" /> <Button Content="瀏覽..." Click="BrowseButton_Click" Width="80" Height="30" Margin="0 0 0 10" /> <TextBox x:Name="FilePathTextBox" Text="{Binding FilePath}" Width="300" Height="30" Margin="0 0 0 10" /> <TextBlock Text="輸入服務端IP地址:" Margin="0 0 0 10" /> <TextBox x:Name="ServerIPTextBox" Text="{Binding ServerIP}" Width="200" Height="30" Margin="0 0 0 10" /> <TextBlock Text="輸入服務端端口號:" Margin="0 0 0 10" /> <TextBox x:Name="ServerPortTextBox" Text="{Binding ServerPort}" Width="100" Height="30" Margin="0 0 0 10" /> <Button Content="上傳" Click="UploadButton_Click" Width="80" Height="30" Margin="0 0 0 10" /> <TextBlock x:Name="ResultTextBlock" Text="{Binding ResultMessage}" Margin="0 10" TextWrapping="Wrap" /> </StackPanel> </Grid></Window>
MainWindow.xaml.cs:
using System;using System.ComponentModel;using System.IO;using System.Net.Sockets;using System.Security.Cryptography;using System.Text;using System.Windows;namespace FileUploaderClient{ public partial class MainWindow : Window, INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private string filePath; public string FilePath { get { return filePath; } set { filePath = value; OnPropertyChanged("FilePath"); } } private string serverIP; public string ServerIP { get { return serverIP; } set { serverIP = value; OnPropertyChanged("ServerIP"); } } private int serverPort; public int ServerPort { get { return serverPort; } set { serverPort = value; OnPropertyChanged("ServerPort"); } } private string resultMessage; public string ResultMessage { get { return resultMessage; } set { resultMessage = value; OnPropertyChanged("ResultMessage"); } } public MainWindow() { InitializeComponent(); DataContext = this; } private void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private void BrowseButton_Click(object sender, RoutedEventArgs e) { Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog(); if (openFileDialog.ShowDialog() == true) { FilePath = openFileDialog.FileName; } } private void UploadButton_Click(object sender, RoutedEventArgs e) { try { // 讀取本地文件 byte[] fileData = File.ReadAllBytes(FilePath); // 連接服務端并發送文件 using (TcpClient client = new TcpClient(ServerIP, ServerPort)) { using (NetworkStream stream = client.GetStream()) { // 發送文件名和文件長度 string fileName = Path.GetFileName(FilePath); byte[] fileNameBytes = Encoding.UTF8.GetBytes(fileName); byte[] fileNameLengthBytes = BitConverter.GetBytes(fileNameBytes.Length); byte[] fileLengthBytes = BitConverter.GetBytes(fileData.Length); stream.Write(fileNameLengthBytes, 0, 4); stream.Write(fileNameBytes, 0, fileNameBytes.Length); stream.Write(fileLengthBytes, 0, 4); // 發送文件內容 int bufferSize = 1024; int bytesSent = 0; while (bytesSent < fileData.Length) { int remainingBytes = fileData.Length - bytesSent; int bytesToSend = Math.Min(bufferSize, remainingBytes); stream.Write(fileData, bytesSent, bytesToSend); bytesSent += bytesToSend; } ResultMessage = "文件上傳成功!"; } } } catch (Exception ex) { ResultMessage = "文件上傳失敗:" + ex.Message; } } }}
使用該客戶端程序,用戶可以選擇本地文件進行上傳,并輸入服務端的IP地址和端口號。客戶端會將選擇的文件發送給服務端進行保存。
這個示例實現了基于TCP協議的文件上傳功能,使用TcpClient和NetworkStream進行連接和數據傳輸。文件被分成較小的數據包進行傳輸,發送前會計算文件名和文件長度,并通過4字節的長度前綴指示接收方應該接收多少數據。
dotnet new wpf -n "FileUploaderServer"
MainWindow.xaml:
<Window x:Class="FileUploaderServer.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="文件上傳服務端" Height="350" Width="500"> <Grid> <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBlock Text="輸入要監聽的端口號:" Margin="0 0 0 10" /> <TextBox x:Name="PortTextBox" Text="{Binding Port}" Width="100" Height="30" Margin="0 0 0 10" /> <Button Content="啟動服務" Click="StartButton_Click" Width="80" Height="30" Margin="0 0 0 10" /> <TextBlock x:Name="ResultTextBlock" Text="{Binding ResultMessage}" Margin="0 10" TextWrapping="Wrap" /> </StackPanel> </Grid></Window>
MainWindow.xaml.cs:
using System;using System.ComponentModel;using System.IO;using System.Net;using System.Net.Sockets;using System.Security.Cryptography;using System.Text;using System.Threading;using System.Windows;namespace FileUploaderServer{ public partial class MainWindow : Window, INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private int port; public int Port { get { return port; } set { port = value; OnPropertyChanged("Port"); } } private string resultMessage; public string ResultMessage { get { return resultMessage; } set { resultMessage = value; OnPropertyChanged("ResultMessage"); } } private TcpListener serverListener; private Thread serverThread; public MainWindow() { InitializeComponent(); DataContext = this; } private void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private void StartButton_Click(object sender, RoutedEventArgs e) { try { // 啟動服務端監聽 IPAddress ipAddress = IPAddress.Any; serverListener = new TcpListener(ipAddress, Port); serverListener.Start(); // 啟動服務端線程 serverThread = new Thread(new ThreadStart(ServerThreadProc)); serverThread.IsBackground = true; serverThread.Start(); ResultMessage = "服務啟動成功!"; } catch (Exception ex) { ResultMessage = "服務啟動失敗:" + ex.Message; } } private void ServerThreadProc() { while (true) { try { // 接受客戶端連接請求 TcpClient client = serverListener.AcceptTcpClient(); // 處理客戶端連接請求 Thread clientThread = new Thread(new ParameterizedThreadStart(ClientThreadProc)); clientThread.IsBackground = true; clientThread.Start(client); } catch (Exception) { break; } } } private void ClientThreadProc(object parameter) { TcpClient client = (TcpClient)parameter; try { using (client) { using (NetworkStream stream = client.GetStream()) { // 讀取文件名和文件長度 byte[] fileNameLengthBytes = new byte[4]; stream.Read(fileNameLengthBytes, 0, 4); int fileNameLength = BitConverter.ToInt32(fileNameLengthBytes, 0); byte[] fileNameBytes = new byte[fileNameLength]; stream.Read(fileNameBytes, 0, fileNameLength); string fileName = Encoding.UTF8.GetString(fileNameBytes); byte[] fileLengthBytes = new byte[4]; stream.Read(fileLengthBytes, 0, 4); int fileLength = BitConverter.ToInt32(fileLengthBytes, 0); // 接收文件內容 int bufferSize = 1024; byte[] buffer = new byte[bufferSize]; int bytesRead = 0; int totalBytesRead = 0; byte[] fileData = new byte[fileLength]; while (totalBytesRead < fileLength && (bytesRead = stream.Read(buffer, 0, Math.Min(bufferSize, fileLength - totalBytesRead))) > 0) { Buffer.BlockCopy(buffer, 0, fileData, totalBytesRead, bytesRead); totalBytesRead += bytesRead; } // 保存文件到本地 string savePath = Path.Combine(Environment.CurrentDirectory, "Uploads", fileName); if (File.Exists(savePath)) { savePath = Path.Combine(Environment.CurrentDirectory, "Uploads", Path.GetFileNameWithoutExtension(fileName) + "_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + Path.GetExtension(fileName)); } using (FileStream fileStream = new FileStream(savePath, FileMode.CreateNew)) { fileStream.Write(fileData, 0, fileLength); } ResultMessage = "文件保存成功:" + savePath; } } } catch (Exception ex) { ResultMessage = "文件保存失敗:" + ex.Message; } } }}
使用該服務端程序,用戶可以輸入要監聽的端口號,并啟動服務端監聽。當有客戶端連接時,服務端會接收文件數據,并保存到指定位置。
這個示例實現了基于TCP協議的文件接收和保存功能,使用TcpListener和TcpClient進行監聽和連接,使用NetworkStream進行數據傳輸。文件被分成較小的數據包進行傳輸,發送前會計算文件名和文件長度,并通過4字節的長度前綴指示接收方應該接收多少數據。
啟動服務端,開啟端口12345。
啟動客戶端程序,配置服務端地址。
本文鏈接:http://www.www897cc.com/showinfo-26-71447-0.html基于TCP協議Socket編程,使用WPF實現文件上傳和保存文件完整示例
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com