zoukankan      html  css  js  c++  java
  • 多线程+Socket文件传输 Demo

    项目需求,实现cs 客户端自动更新,由于文件很大,只能通过socket 传输更新文件,这样服务器端需要把更新的文件发送到客户端。

    基于此,做了一个Demo,案例简单,关键部分都有注释,文章最后附加源文件下载。希望对于正在学习socket 文件传输的同学有所帮助

    服务端文件:

     

    服务端文件
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Net.Sockets;
    using System.Net;
    using System.Threading;
    using System.IO;

    namespace FileServer
    {
        public partial class Form2 : Form
        { 
            Socket Listensocket;
            Thread listenThread;
           
            public Form2()
            {
                InitializeComponent();
            }

            //选择文件
            private void BtnSelectFile_Click(object sender, EventArgs e)
            {
                if (this.openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    FileInfo fileinfo = new FileInfo(this.openFileDialog1.FileName);
                    tbFileName.Text = fileinfo.FullName;
                    tbFileSize.Text = fileinfo.Length.ToString();
                }
            }
            
            //开始监听
            private void btnListen_Click(object sender, EventArgs e)
            {
                if (!string.IsNullOrEmpty(tbFileName.Text) && !string.IsNullOrEmpty(tbFileSize.Text))
                {
                    //服务端节点    
                    IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("192.168.1.100"), 8080);

                    //创建套接字         
                    Listensocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                    //绑定IP地址和端口到套接字    
                    Listensocket.Bind(ipep);

                    //启动监听          
                    Listensocket.Listen(10);
                    listBox1.Items.Add("开始监听客户端的连接请求");

                    //在一个单独的线程中监听客户连接       
                    listenThread = new Thread(listenClientConnnect);
                    listenThread.Start();
                    btnListen.Enabled = false;
                }
                else
                {
                    MessageBox.Show("请浏览文件""提醒信息");
                }
            }
               
            //监听函数
            private void listenClientConnnect()
            {
                stopListen();//停用
                while (true)
                {
                    //建立一个与客户端通信的套接字 
                    Socket CommunicationSocket = Listensocket.Accept();

                    //显示在listbox里面
                    IPEndPoint clientIP = (IPEndPoint)CommunicationSocket.RemoteEndPoint;
                   
                    AddMsg(string.Format("{0} 连接到本服务器 {1}", clientIP.Address, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));

                    //创建一个文件对象     
                    FileInfo fileinfo = new FileInfo(tbFileName.Text);

                    //打开文件流            
                    FileStream filestream = fileinfo.OpenRead();

                    //文件分块传输,分块的大小,单位为字节         
                    int PacketSize = 5000;
                    //分块的数量               
                    int PacketCount = (int)(fileinfo.Length / ((long)PacketSize));
                    //最后一个分块的大小           
                    int LastPacketSize = (int)(fileinfo.Length - ((long)(PacketSize * PacketCount)));

                    //发送文件名到接收端,文件名长度最多只允许100个字节       
                    byte[] Fullfilename = new byte[100];
                    if (System.Text.Encoding.UTF8.GetBytes(fileinfo.Name).Length > 100)
                    {
                        MessageBox.Show("文件名太长");
                        break;
                    }
                    else
                    {
                        byte[] filename = System.Text.Encoding.UTF8.GetBytes(fileinfo.Name);
                        for (int i = 0; i < filename.Length; i++)
                            Fullfilename[i] = filename[i];
                        CommunicationSocket.Send(Fullfilename);
                    }


                    //文件按数据包的形式发送,定义数据包的大小      
                    byte[] data = new byte[PacketSize];
                    //开始循环发送数据包           
                    for (int i = 0; i < PacketCount; i++)
                    {
                        //从文件流读取数据并填充数据包  
                        filestream.Read(data, 0, data.Length);
                        //发送数据包                    
                        CommunicationSocket.Send(data, 0, data.Length, SocketFlags.None);
                    }
                    //发送最后一个数据包   
                    if (LastPacketSize != 0)
                    {
                        data = new byte[LastPacketSize];
                        filestream.Read(data, 0, data.Length);
                        //发送数据包             
                        CommunicationSocket.Send(data, 0, data.Length, SocketFlags.None);
                    }
                    filestream.Close();
                    CommunicationSocket.Close();               
                    AddMsg(string.Format("向{0} 发送 文件 已完成 {1}", clientIP, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
                }
            }

            //关闭
            private void Form2_FormClosed(object sender, FormClosedEventArgs e)
            {
                if (Listensocket!=null)
                { 
                    Listensocket.Close();    
                }
            }

            //停止监听
            private void btnStop_Click(object sender, EventArgs e)
            {
                if (listenThread.IsAlive)
                {
                    listenThread.Abort();
                    btnListen.Enabled = true;
                    btnStop.Enabled = false;
                    if (Listensocket!=null)
                    {
                        Listensocket.Close();
                    }
                    listBox1.Items.Add("服务器监听已经停止...");

                }
            }

            //加载
            private void Form2_Load(object sender, EventArgs e)
            {
                btnStop.Enabled = false;
                btnListen.Enabled = true;
            }

            //停止监听
            private void stopListen()
            {
                if (btnStop.InvokeRequired)
                {
                    Action stopAction = () => { stopListen(); };
                    btnStop.Invoke(stopAction);
                }
                else
                {
                    btnStop.Enabled = true;
                }
            }

            //向listBox中增加信息
            private void AddMsg(string msgStr)
            {
                if (listBox1.InvokeRequired)
                {
                    Action<string> myAction = (p) => { AddMsg(p); };
                    this.listBox1.Invoke(myAction, msgStr);
                }
                else
                {
                    this.listBox1.Items.Add(msgStr);
                }
            }
        }
    }

    客户端文件:

    客户端程序
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Threading;
    using System.Net.Sockets;
    using System.Net;

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

            //连接
            private void btnConnect_Click(object sender, EventArgs e)
            {
                Thread mythread = new Thread(GetData); 
                mythread.Start();
            }

            //接受数据
            private void GetData()
            {
                IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("192.168.1.100"), 8080);
                Socket clientsocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                try
                {
                    listBox1.Items.Add("连接远程服务器成功");
                    clientsocket.Connect(ipep);
                }
                catch (Exception)
                {
                    listBox1.Items.Add("连接远程服务器失败");
                }

                //接收文件的名称          
                string filename = System.Text.Encoding.UTF8.GetString(ReceiveStrToByte(clientsocket)).Split('\0')[0];
               
                //创建一个新文件        
                FileStream MyFileStream = new FileStream(filename, FileMode.Create, FileAccess.Write);

                int PacketSize = 5000;
                //定义一个完整数据包缓存  
                byte[] data = new byte[PacketSize];
                while (true)
                {
                    int revcount = clientsocket.Receive(data, 0, PacketSize, SocketFlags.None);
                    if (revcount == 0)
                    {
                        data = null;
                        break;
                    }
                    //处理最后一个数据包    
                    if (revcount != PacketSize)
                    {
                        byte[] lastdata = new byte[revcount];
                        for (int i = 0; i < revcount; i++)
                            lastdata[i] = data[i];
                        //将接收到的最后一个数据包写入到文件流对象      
                        MyFileStream.Write(lastdata, 0, lastdata.Length);
                        lastdata = null;
                    }
                    else
                    {
                        //将接收到的数据包写入到文件流对象      
                        MyFileStream.Write(data, 0, data.Length);
                    }
                }
                //关闭文件流       
                MyFileStream.Close();
                //关闭套接字           
                clientsocket.Close();
                listBox1.Items.Add(string.Format("{0}接收完毕", filename));
              
            }

            private byte[] ReceiveStrToByte(Socket s)
            {
                try
                {
                    byte[] dataninfo = new byte[100];
                    int revByteNum = s.Receive(dataninfo, 0, dataninfo.Length, SocketFlags.None);
                    byte[] retByte = new byte[revByteNum];
                    for (int i = 0; i < revByteNum; i++)
                        retByte[i] = dataninfo[i];
                    return retByte;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    return null;
                }
            }
        }
    }

    程序源文件下载:源程序下载

  • 相关阅读:
    集合
    3/11
    字典
    3/10
    字符串之不常用方法
    字符串的索引和切片
    数据类型的转化
    Markdown在线编辑器
    3/9
    Django:RestFramework之-------渲染器
  • 原文地址:https://www.cnblogs.com/clc2008/p/2615372.html
Copyright © 2011-2022 走看看