基于Socket通信的BS结构文件服务器客户端的简易程序(2)

http://blog.csdn.net/weixingstudio/article/details/7042266

 

下面是客户端的所有代码,整个程序的源码下载连接会在下一篇给出。

 

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.Threading;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Collections.Specialized;

namespace Client
{
    public partial class MainForm : Form
    {
        // 服务器和客户机协约的通信协议
        // "00" 同意连接
        // "01" 拒绝连接
        // "10" 用户请求离线
        // "11" 通知用户刷新在线用户列表
        // "12" 请求在线用户列表
        // ""

        private string userName;
        private NetworkStream netStream = null;
        private Thread receiveThread = null;
        private int maxBuffer = 1024 * 1024; // 最大文件1M
        private int fileBuffer_eachTime_sended = 8 * 1024;// 每次最多传送8K , 先这样测测

        private delegate void setOnlineuserDelegate(string s);
        private delegate void flashFileListDelegate(StringCollection sc);
        //private byte[] file_byte;

        // 添加一个变量,用来标识窗口是不是第一次启动,并且需要刷新文件列表
        private bool isFlashFilesNeeded = true;

        public MainForm(string user_Name, NetworkStream networkStream)
        {
            InitializeComponent();
            userName = user_Name;
            netStream = networkStream; // 通过窗口间的参数传递来传递用来给Socket通信用的NetwokStream
            this.FormClosed += new FormClosedEventHandler(MainForm_FormClosed);
            receiveThread = new Thread(new ThreadStart(receive));
            //receiveThread.ApartmentState = ApartmentState.STA;
            //Thread.CurrentThread.SetApartmentState(ApartmentState.STA);
            receiveThread.SetApartmentState(ApartmentState.STA);
            // 开启接收信息线程
            receiveThread.Start();
        }

        /// <summary>
        /// 客户端接收信息的处理函数
        /// </summary>
        private void receive()
        {
            // 初始化在线用户列表,给服务器发送一个请求在线用户列表命令
            netStream.Write(new byte[] { 1, 2 }, 0, 2);
            // 通过循环操作不停的和服务器进行通信
            while(true)
            {
                byte[] cmd = new byte[4];
                netStream.Read(cmd,0,cmd.Length);
                string command = DecodingBytes(cmd);
                switch(command)
                {
                    // 服务器发送用户请求连线命令,没有实际意义
                    case "10":
                        {
                            break;
                        }
                    // 通知用户刷新在线用户列表
                    case "11":
                        {
                            //先发送了一个命令,然后发送在线用户列表的信息
                            byte[] onlineUserListBuffer=new byte[maxBuffer];
                            int byteCnt = netStream.Read(onlineUserListBuffer, 0, onlineUserListBuffer.Length);
                            // 进行反序列化
                            IFormatter format = new BinaryFormatter();
                            MemoryStream stream = new MemoryStream();
                            stream.Write(onlineUserListBuffer, 0, byteCnt);
                            stream.Position = 0;
                            StringCollection onlineList = (StringCollection)format.Deserialize(stream);
                            // 清空原始信息
                            string temp = "";
                            // 线程安全的清空控件中的文本信息
                            clearOnLineUserList(temp);
                            foreach (string onliner in onlineList)
                            {
                                // 线程安全的给控件添加信息
                                flashOnlineUser(onliner);
                            }

                            // 通过判断刷新文件列表
                            if (isFlashFilesNeeded)
                            {
                                // 请求文件列表
                                netStream.Write(new byte[] { 4, 4 }, 0, 2);
                                isFlashFilesNeeded = false;
                            }
                            break;
                        }
                    // 服务器通知客户端有人上线
                    case "22":
                        {
                            byte[] buffer=new byte[64];
                            netStream.Read(buffer,0,buffer.Length);
                            string info = Encoding.Unicode.GetString(buffer).TrimEnd('\0');
                            this.toolStripStatusLabel1.Text = info;
                            // 有人上线以后需要刷新在线用户列表
                            netStream.Write(new byte[] { 1, 2 }, 0, 2);
                            break;
                        }
                    // 服务器通知客户端有用户离线
                    case "23":
                        {
                            byte[] buffer = new byte[64];
                            netStream.Read(buffer, 0, buffer.Length);
                            string info = Encoding.Unicode.GetString(buffer).TrimEnd('\0');
                            this.toolStripStatusLabel1.Text = info;
                            // 有人离线后需要刷新在线用户列表
                            netStream.Write(new byte[] { 1, 2 }, 0, 2);
                            break;
                        }
                    // 服务器通知文件上传成功
                    case "34":
                        {
                            //Thread.Sleep(50);
                            MessageBox.Show("文件上传成功!");
                            // 刷新文件列表
                            netStream.Write(new byte[] { 4, 4 }, 0, 2);
                            break;
                        }
                    // 服务器给用户返回文件列表
                    case "45":
                        {
                            byte[] buffer=new byte[8196];
                            int byteCnt = netStream.Read(buffer, 0, buffer.Length);
                            // 文件列表的反序列化
                            IFormatter format = new BinaryFormatter();
                            MemoryStream stream = new MemoryStream();
                            stream.Write(buffer, 0, byteCnt);
                            stream.Position = 0;
                            // 下列代码已执行
                            StringCollection fileList = (StringCollection)format.Deserialize(stream);
                            // 线程安全的给控件添加信息
                            flashFileList(fileList);
                            break;
                        }
                    // 服务器给用户传送文件
                    case "56":
                        {
                            byte[] buffer = new byte[fileBuffer_eachTime_sended]; // 每次传送的次数
                            SaveFileDialog sFD = new SaveFileDialog();
                            sFD.Filter = "txt files(*.txt)|*.txt|Image Files(*.BMP;*.JPG;*.GIF)|*.BMP;*.JPG;*.GIF|All files(*.*)|*.*";
                            if (sFD.ShowDialog() == DialogResult.OK)
                            {
                                string fileName = sFD.FileName;
                                //MessageBox.Show(fileName);
                                // 保存文件
                                FileStream file = File.Open(fileName, FileMode.Create);
                                BinaryWriter bw = new BinaryWriter(file);
                                 接收需要发送的次数
                                //byte[] receive_num=new byte[8];
                                //netStream.Read(receive_num, 0, 8);
                                //string temp_receive_num = Encoding.Unicode.GetString(receive_num).TrimEnd('\0');
                                byte[] sumFile_byte = new byte[16];
                                // 接收总的文件大小
                                netStream.Read(sumFile_byte, 0, sumFile_byte.Length);
                                string t = Encoding.Unicode.GetString(sumFile_byte).TrimEnd('\0');
                                string tt = t;
                                char[] xyz=tt.ToCharArray();
                                int count = 0;
                                foreach (char c in xyz)
                                {
                                    if (c >= '0' && c <= '9')
                                    {
                                        count++;
                                    }
                                }
                                tt = tt.Substring(0,count);
                                long fileSize = Convert.ToInt64(tt,10);
                                int receive_number_int = (int)(fileSize / fileBuffer_eachTime_sended) + 1;
                                // 向文件中写数据
                                if (receive_number_int == 1)
                                {
                                    // 只需要传送一次
                                    int FileSize = netStream.Read(buffer, 0, fileBuffer_eachTime_sended);
                                    //int FileSize = clientSocket.Receive(fileBuffer);
                                    bw.Write(buffer, 0, FileSize);
                                    bw.Flush(); 
                                }
                                else if (receive_number_int > 1)
                                {
                                    // 需要多次接收文件
                                    for (int i = 1; i < receive_number_int; i++)
                                    {
                                        netStream.Read(buffer, 0, fileBuffer_eachTime_sended);
                                        //clientSocket.Receive(fileBuffer);
                                        bw.Write(buffer, 0, fileBuffer_eachTime_sended);
                                        bw.Flush();
                                    }
                                    // 计算最后需要接收的字节数
                                    int num_remain = (int)(fileSize % fileBuffer_eachTime_sended);
                                    byte[] newBuffer = new byte[num_remain];
                                    netStream.Read(newBuffer, 0, num_remain);
                                    bw.Write(newBuffer, 0, num_remain);
                                    bw.Flush();
                                }
                                // 向文件中写数据
                                bw.Close();
                                file.Close();
                            }
                            break;
                        }
                    // 删除文件成功
                    case "67":
                        {
                            MessageBox.Show("删除文件成功");
                            // 刷新文件列表
                            netStream.Write(new byte[] { 4, 4 }, 0, 2);
                            break; 
                        }
                }
            }
        }

        /// <summary>
        /// 线程安全的在控件中显示文件列表
        /// </summary>
        /// <param name="sc"></param>
        private void flashFileList(StringCollection sc)
        {
            if (this.listView1.InvokeRequired)
            {
                flashFileListDelegate call = delegate(StringCollection t)
                {
                    // 清空以前的
                    this.listView1.Items.Clear();
                    int length = t.Count;
                    string[] fileInfo = new string[length];
                    int i = 0;
                    foreach (string s in t)
                    {
                        fileInfo[i] = s;
                        i++;
                    }
                    i = 1;
                    // 计算每一行,一共有多少行
                    for (i = 0; i < length / 3; i++)
                    {
                        ListViewItem lvi = new ListViewItem();
                        lvi.Text = fileInfo[i * 3];
                        lvi.SubItems.Add(fileInfo[i * 3 + 1]);
                        lvi.SubItems.Add(fileInfo[i * 3 + 2]);
                        this.listView1.Items.Add(lvi);
                    }
                };
                this.listView1.Invoke(call, sc);
            }
            else
            {
                // 清空以前的
                this.listView1.Clear();

                int length = sc.Count;
                string[] fileInfo = new string[length];
                int i = 0;
                foreach (string s in sc)
                {
                    fileInfo[i] = s;
                    i++;
                }
                i = 1;
                // 计算每一行,一共有多少行
                for (i = 0; i < length / 3; i++)
                {
                    ListViewItem lvi = new ListViewItem();
                    lvi.Text = fileInfo[i];
                    lvi.SubItems.Add(fileInfo[i + 1]);
                    lvi.SubItems.Add(fileInfo[i + 2]);
                    this.listView1.Items.Add(lvi);
                }
            }
        }

        /// <summary>
        /// 线程安全的清空控件信息
        /// </summary>
        /// <param name="s"></param>
        private void clearOnLineUserList(string s)
        {
            if (this.userList.InvokeRequired)
            {
                setOnlineuserDelegate call = delegate(string ss) { this.userList.Text = ss; };
                this.userList.Invoke(call, s);
            }
            else
            {
                this.userList.Text = s;
            }
        }

        private void flashOnlineUser(string userName)
        {
            if (this.userList.InvokeRequired)
            {
                setOnlineuserDelegate call = delegate(string s) { this.userList.Text += s + "\n"; };
                this.userList.Invoke(call, userName);
            }
            else
            {
                this.userList.Text += "\n" + userName;
            }
        }

        private string DecodingBytes(byte[] s)
        {
            return string.Concat(s[0].ToString(), s[1].ToString());
        }

        /// <summary>
        /// 关闭窗口之前判断连接是否断开,如果连接没有断开则调用关闭连接的服务
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void MainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            //throw new NotImplementedException();
            if (netStream == null)
            {
                //关闭父窗口及自身===========
                this.Owner.Close();
                this.Close();
            }
            else
            {
                // 先关闭网络流,在关闭窗口
                // 给服务器发送断开连接请求
                DialogResult ret;
                ret = MessageBox.Show("确定与服务器断开连接吗?",
                                        "退出",
                                        MessageBoxButtons.OKCancel,
                                        MessageBoxIcon.Question,
                                        MessageBoxDefaultButton.Button2);

                if (ret == DialogResult.OK)
                {
                    //向服务器发送离线请求
                    netStream.Write(new byte[] { 1, 0 }, 0, 2);
                    if (receiveThread != null)
                    {
                        // 终止接受信息进程
                        receiveThread.Abort();
                        receiveThread = null;
                    }
                    // 关闭网络流连接
                    netStream.Close();
                    //关闭父窗口及自身===========
                    //this.Owner.Close();
                    //this.Close();
                }
                else
                { }
            }

        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            toolStripStatusLabel1.Text = "welcome to use this system! Developped by WeiSONG";
            Thread.CurrentThread.SetApartmentState(ApartmentState.STA);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (this.openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    string filePath = openFileDialog1.FileName;
                    //MessageBox.Show(filePath);
                    FileStream fs = File.Open(filePath, FileMode.Open);
                    long fileSize = fs.Length;
                    // 如果文件大小超过规定的值,则弹出提示消息,退出操作
                    if (fileSize >= maxBuffer)
                    {
                        MessageBox.Show("对不起,您选择上传的文件过大,本系统暂时不支持!", "INFO");
                        return;
                    }
                    // 计算需要发送的次数
                    int times_tobesended = (int)fileSize / fileBuffer_eachTime_sended + 1;
                    BinaryReader br = new BinaryReader(fs);
                    // 用来存储即将发送的数据
                    byte[] bytes_tobesend = new byte[fileBuffer_eachTime_sended];

                    // 获取文件名
                    string[] temp = filePath.Split('\\');
                    int k = temp.Length;
                    string fileName = temp[k - 1];
                    //MessageBox.Show(fileName);
                    // 给服务器发送上传文件请求
                    netStream.Write(new byte[] { 3, 3 }, 0, 2);
                    netStream.Flush();
                    // 给服务器发送要传送的文件名
                    netStream.Write(Encoding.Unicode.GetBytes(fileName), 0, Encoding.Unicode.GetBytes(fileName).Length);

                    // 给服务器传送需要文件发送的次数
                    //netStream.Write(Encoding.Unicode.GetBytes(times_tobesended.ToString()), 0, Encoding.Unicode.GetBytes(times_tobesended.ToString()).Length);
                    // 给服务器发送总的文件大小
                    netStream.Write(Encoding.Unicode.GetBytes(fileSize.ToString()), 0, Encoding.Unicode.GetBytes(fileSize.ToString()).Length);
                    // 开始传送文件
                    if (times_tobesended == 1)
                    {
                        // 只需要传送一次
                        byte[] bytes_Only1time=new byte[fileSize];
                        br.Read(bytes_Only1time, 0, (int)fileSize);
                        netStream.Write(bytes_Only1time, 0, (int)fileSize);
                    }
                    else if (times_tobesended > 1)
                    {
                        // 需要传送的次数>1, 需要分多次传送
                        for (int i = 1; i < times_tobesended; i++)
                        {
                            bytes_tobesend = br.ReadBytes(fileBuffer_eachTime_sended);
                            //br.Read(bytes_tobesend, 0, fileBuffer_eachTime_sended);
                            netStream.Write(bytes_tobesend,0,fileBuffer_eachTime_sended);
                            netStream.Flush();
                            Thread.Sleep(10);
                        }
                        // 最后一次传送所有剩余的字节
                        int remainedBytes = (int)(fileSize % fileBuffer_eachTime_sended); // 计算剩余的字节数 
                        byte[] to_be_send_remain = new byte[remainedBytes];
                        to_be_send_remain = br.ReadBytes(remainedBytes);
                        //br.Read(bytes_tobesend, 0, remainedBytes);
                        netStream.Write(to_be_send_remain, 0, remainedBytes);
                        netStream.Flush();
                        //Thread.Sleep(10);
                    } 
                    br.Close();
                    fs.Close();
                }
                catch(FileLoadException)
                {
                    //
                }
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //  请求文件列表
            netStream.Write(new byte[] { 4, 4 }, 0, 2);
            netStream.Flush();

            // 获取选中的行
            //string test = this.listView1.SelectedItems[0].Text;
            //MessageBox.Show(test);
            this.listView1.Items.Add("test","aaa","bbb");
            //ListViewItem lvi = new ListViewItem();
            //lvi.Text = "第一列信息";
            //lvi.SubItems.Add("第二列");
            //this.listView1.Items.Add(lvi);
            //ListViewItem lv2 = new ListViewItem();
            //lv2.Text = "第二列信息";
            //this.listView1.Items.Add(lv2);
        }

        private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {
            //
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (this.listView1.SelectedItems.Count == 0)
            {
                MessageBox.Show("请选择好文件以后在选择下载");
            }
            else
            {
                string fileName = this.listView1.SelectedItems[0].Text; // 获取选择的文件名
                // 给服务器发送下载文件请求
                netStream.Write(new byte[] { 5, 5 }, 0, 2);
                byte[] fileName_byte = Encoding.Unicode.GetBytes(fileName);
                // 发送要下载的文件名
                netStream.Write(fileName_byte, 0, fileName_byte.Length);
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            if (this.listView1.SelectedItems.Count == 0)
            {
                MessageBox.Show("请选择好文件以后在选择删除");
            }
            else
            {
                string fileName = this.listView1.SelectedItems[0].Text;
                byte[] fileName_byte = Encoding.Unicode.GetBytes(fileName);
                // 先发送请求指令
                netStream.Write(new byte[] { 6, 6 }, 0, 2);
                // 发送文件名
                netStream.Write(fileName_byte, 0, fileName_byte.Length);
            }
        }

        //private void disconnectToolStripMenuItem_Click(object sender, EventArgs e)
        //{
        //    // 给服务器发送断开连接请求
        //    DialogResult ret;
        //    ret = MessageBox.Show("确定与服务器断开连接吗?",
        //                          "退出",
        //                          MessageBoxButtons.OKCancel,
        //                          MessageBoxIcon.Question,
        //                          MessageBoxDefaultButton.Button2);

        //    if (ret == DialogResult.OK)
        //    {
        //        //向服务器发送离线请求
        //        netStream.Write(new byte[] { 1, 0 }, 0, 2);
        //        if (receiveThread != null)
        //        {
        //            // 终止接受信息进程
        //            receiveThread.Abort();
        //        }
        //        // 关闭网络流连接
        //        netStream.Close();
        //        //关闭父窗口及自身===========
        //        this.Owner.Close();
        //        this.Close();
        //    }
        //}
    }
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值