多线程+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;
            }
        }
    }
}

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

 

posted @ 2012-07-30 15:44  lance2008  阅读(4717)  评论(3编辑  收藏  举报