文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2024-11-30 02:06

关注

需求分析

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

1、客户端需求:

2、服务端需求:

3、文件传输需求:

4、错误处理需求:

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

客户端代码和实现过程

dotnet new wpf -n "FileUploaderClient"

MainWindow.xaml:


    
        
            
            

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:


    
        
            
            
            

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。

启动客户端程序,配置服务端地址。

来源:今日头条内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯