当前位置:首页 > 科技  > 软件

基于TCP协议Socket编程,使用WPF实现文件上传和保存文件完整示例

来源: 责编: 时间:2024-02-02 09:20:06 122观看
导读需求分析假设我们需要实现一个基于网络的文件上传系统,用户可以通过客户端将本地文件上传到服务端。这种情况经常出现在文件存储和共享、云存储等应用场景中。使用Socket编程可以实现高效可靠的文件传输。1、客户端需

7cf28资讯网——每日最新资讯28at.com

需求分析

假设我们需要实现一个基于网络的文件上传系统,用户可以通过客户端将本地文件上传到服务端。这种情况经常出现在文件存储和共享、云存储等应用场景中。使用Socket编程可以实现高效可靠的文件传输。7cf28资讯网——每日最新资讯28at.com

1、客户端需求:

  • 用户可以选择本地文件进行上传。
  • 用户需要输入服务端的IP地址和端口号。
  • 客户端需要将选择的文件发送给服务端进行保存。

2、服务端需求:

  • 服务端需要监听指定的端口,等待客户端连接请求。
  • 接收到客户端连接后,服务端需要接收文件数据。
  • 服务端需要将接收到的文件保存到指定位置。

3、文件传输需求:

  • 传输协议:使用TCP协议确保可靠的数据传输。
  • 文件分片:为了减小内存开销和网络负载,将大文件分成多个较小的数据包进行传输。
  • 文件校验:传输过程中需要对文件进行校验,确保数据的完整性。

4、错误处理需求:

  • 连接错误:需要处理连接失败、超时等错误情况。
  • 文件错误:需要处理文件读取失败、传输中断等错误情况。
  • 异常处理:需要处理网络异常、IO异常等情况,并提供相应的错误提示和处理机制。

基于以上需求,我们可以使用C#的Socket编程实现一个文件上传系统,包括客户端和服务端的程序。在程序中使用Socket进行网络连接和数据传输,同时对连接错误和文件错误进行适当处理和异常捕获。7cf28资讯网——每日最新资讯28at.com

客户端代码和实现过程

dotnet new wpf -n "FileUploaderClient"

MainWindow.xaml:7cf28资讯网——每日最新资讯28at.com

<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>

7cf28资讯网——每日最新资讯28at.com

MainWindow.xaml.cs:7cf28资讯网——每日最新资讯28at.com

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地址和端口号。客户端会将选择的文件发送给服务端进行保存。7cf28资讯网——每日最新资讯28at.com

这个示例实现了基于TCP协议的文件上传功能,使用TcpClient和NetworkStream进行连接和数据传输。文件被分成较小的数据包进行传输,发送前会计算文件名和文件长度,并通过4字节的长度前缀指示接收方应该接收多少数据。7cf28资讯网——每日最新资讯28at.com

服务端代码和实现过程

dotnet new wpf -n "FileUploaderServer"

MainWindow.xaml:7cf28资讯网——每日最新资讯28at.com

<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>

7cf28资讯网——每日最新资讯28at.com

MainWindow.xaml.cs:7cf28资讯网——每日最新资讯28at.com

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;            }        }    }}

使用该服务端程序,用户可以输入要监听的端口号,并启动服务端监听。当有客户端连接时,服务端会接收文件数据,并保存到指定位置。7cf28资讯网——每日最新资讯28at.com

这个示例实现了基于TCP协议的文件接收和保存功能,使用TcpListener和TcpClient进行监听和连接,使用NetworkStream进行数据传输。文件被分成较小的数据包进行传输,发送前会计算文件名和文件长度,并通过4字节的长度前缀指示接收方应该接收多少数据。7cf28资讯网——每日最新资讯28at.com

运行结果

启动服务端,开启端口12345。7cf28资讯网——每日最新资讯28at.com

7cf28资讯网——每日最新资讯28at.com

启动客户端程序,配置服务端地址。7cf28资讯网——每日最新资讯28at.com

7cf28资讯网——每日最新资讯28at.com

7cf28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-71447-0.html基于TCP协议Socket编程,使用WPF实现文件上传和保存文件完整示例

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: HaLow Wi-Fi 标准被证明大有可为:实现 3 公里稳定无线连接

下一篇: Vue的缓存组件知道多少?实例代码详解KeepAlive

标签:
  • 热门焦点
  • 天猫精灵Sound Pro体验:智能音箱没有音质?来听听我的

    天猫精灵Sound Pro体验:智能音箱没有音质?来听听我的

    这几年除了手机作为智能生活终端最主要的核心之外,第二个可以成为中心点的产品是什么?——是智能音箱。 手机在执行命令的时候有两种操作方式,手和智能语音助手,而智能音箱只
  • 太卷!Redmi MAX 100英寸电视便宜了:12999元买Redmi史上最大屏

    太卷!Redmi MAX 100英寸电视便宜了:12999元买Redmi史上最大屏

    8月5日消息,从小米商城了解到,Redmi MAX 100英寸巨屏电视日前迎来官方优惠,到手价12999元,比发布价便宜了7000元,在大屏电视市场开卷。据了解,Redmi MAX 100
  • Raft算法:保障分布式系统共识的稳健之道

    Raft算法:保障分布式系统共识的稳健之道

    1. 什么是Raft算法?Raft 是英文”Reliable、Replicated、Redundant、And Fault-Tolerant”(“可靠、可复制、可冗余、可容错”)的首字母缩写。Raft算法是一种用于在分布式系统
  • CSS单标签实现转转logo

    CSS单标签实现转转logo

    转转品牌升级后更新了全新的Logo,今天我们用纯CSS来实现转转的新Logo,为了有一定的挑战性,这里我们只使用一个标签实现,将最大化的使用CSS能力完成Logo的绘制与动画效果。新logo
  • 学习JavaScript的10个理由...

    学习JavaScript的10个理由...

    作者 | Simplilearn编译 | 王瑞平当你决心学习一门语言的时候,很难选择到底应该学习哪一门,常用的语言有Python、Java、JavaScript、C/CPP、PHP、Swift、C#、Ruby、Objective-
  • 在线图片编辑器,支持PSD解析、AI抠图等

    在线图片编辑器,支持PSD解析、AI抠图等

    自从我上次分享一个人开发仿造稿定设计的图片编辑器到现在,不知不觉已过去一年时间了,期间我经历了裁员失业、面试找工作碰壁,寒冬下一直没有很好地履行计划.....这些就放在日
  • 三万字盘点 Spring 九大核心基础功能

    三万字盘点 Spring 九大核心基础功能

    大家好,我是三友~~今天来跟大家聊一聊Spring的9大核心基础功能。话不多说,先上目录:图片友情提示,本文过长,建议收藏,嘿嘿嘿!一、资源管理资源管理是Spring的一个核心的基础功能,不
  • 联想的ThinkBook Plus下一版曝光,键盘旁边塞个平板

    联想的ThinkBook Plus下一版曝光,键盘旁边塞个平板

    ThinkBook Plus 是联想的一个特殊笔记本类别,它在封面放入了一块墨水屏,也给人留下了较为深刻的印象。据有人爆料,联想的下一款 ThinkBook Plus 可能更特殊,它
  • 外交部:美方应停止在网络安全问题上不负责任地指责他国

    外交部:美方应停止在网络安全问题上不负责任地指责他国

      中国外交部今天(16日)举行例行记者会。会上,有记者问,美国情报官员称,他们正在阻拦来自中国以及其他国家的黑客获取相关科研成果。 中方对此有何评论?对此
Top