C# 简单通信(实现文件传输)

之前写过一个简单通信传输,不过只有聊天的功能,现在实现了文件传输的功能,借鉴于网上一篇博客,不过他写的仅仅是客户端对于服务器发送文件,我稍微优化了这个功能,实现了,端与端之间信息的互发和文件的互发,感觉学习这些新的东西,还刚开始,进度很慢,很多东西都需要从新去学习,不过慢慢来!Fighting!!!



服务器:



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;

namespace EasyChat
{
    public partial class Server : Form
    {
        public Server()
        {
            InitializeComponent();
            //关闭对文本框的非法线程操作检查
            TextBox.CheckForIllegalCrossThreadCalls = false;
        }

        private void Server_Load(object sender, EventArgs e)
        {
            textIP.AppendText("127.0.0.1");
            textPORT.AppendText("5555");
        }

        Thread threadWatch = null;
        Socket socketWatch = null;
        

        private void ServerBegin_Click(object sender, EventArgs e)
        {
            //定义一个套接字,监听发来的信息,包含3个参数(IP4寻址协议,流式连接,TCP协议)
            socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            int port = Convert.ToInt32(textPORT.Text.Trim());
            IPAddress ip = IPAddress.Parse(textIP.Text.Trim());
            //绑定IP地址和端口号
            IPEndPoint ipe = new IPEndPoint(ip, port);
            socketWatch.Bind(ipe);
            socketWatch.Listen(20);//监听队列长度,20
            //负责监听的线程
            threadWatch = new Thread(WatchConnect);
            //。。。
            threadWatch.IsBackground = true;
            threadWatch.Start();
            Message.AppendText("服务器已经启动,开始监听..."+"\r\n");
        }

        Socket socketConnect = null;

        private void WatchConnect()
        {
            while (true)
            {
                try
                {
                    socketConnect = socketWatch.Accept();
                }
                catch (Exception ex)
                {
                    Message.AppendText(ex.Message);
                    break;
                }
                Message.AppendText("客户端连接成功,可以开始通信..."+"\r\n");
                //创建通信线程,感觉这个和Thread的区别,就是这个有参,另一个无参
                ParameterizedThreadStart pts = new ParameterizedThreadStart(ServerRec);
                Thread thr = new Thread(pts);
                thr.Start(socketConnect);
            }
        }

        string recStr = null;
        private void ServerRec(object obj)
        {
            Socket socketServer = obj as Socket;
            long fileLength = 0;
            
            while (true)
            {
                int firstRcv = 0;
                byte[] buffer = new byte[8 * 1024];
                try
                {
                    //获取接受数据的长度,存入内存缓冲区,返回一个字节数组的长度
                    if (socketServer != null) firstRcv = socketServer.Receive(buffer);

                    if (firstRcv > 0)//大于0,说明有东西传过来
                    {
                        if (buffer[0] == 0)//0对应文字信息
                        {
                            recStr = Encoding.UTF8.GetString(buffer, 1, firstRcv - 1);
                            Message.AppendText("ZXY: " + GetTime() + "\r\n" + recStr + "\r\n");
                        }

                        if (buffer[0] == 1)//1对应文件信息
                        {
                            string filenameSuffix = recStr.Substring(recStr.LastIndexOf("."));
                            SaveFileDialog sfDialog = new SaveFileDialog()
                            {
                                Filter = "(*" + filenameSuffix + ")|*" + filenameSuffix + "",
                                FileName = recStr
                            };

                            if (sfDialog.ShowDialog(this) == DialogResult.OK)
                            {
                                string savePath = sfDialog.FileName;
                                int rec = 0;
                                long recFileLength = 0;
                                bool firstWrite = true;
                                using (FileStream fs = new FileStream(savePath, FileMode.Create, FileAccess.Write))
                                {
                                    while (recFileLength < fileLength)
                                    {
                                        if (firstWrite)
                                        {
                                            fs.Write(buffer, 1, firstRcv - 1);
                                            fs.Flush();
                                            recFileLength += firstRcv - 1;
                                            firstWrite = false;
                                        }
                                        else
                                        {
                                            rec = socketServer.Receive(buffer);
                                            fs.Write(buffer, 0, rec);
                                            fs.Flush();
                                            recFileLength += rec;
                                        }
                                    }
                                    fs.Close();
                                }

                                string fName = savePath.Substring(savePath.LastIndexOf("\\") + 1);
                                string fPath = savePath.Substring(0, savePath.LastIndexOf("\\"));
                                Message.AppendText("ZXY: " + GetTime() + "\r\n你成功接收了文件..." + fName + "\r\n保存路径为:" + fPath + "\r\n");
                            }
                        }
                        if (buffer[0] == 2)//2对应文件名字和长度
                        {
                            string fileNameWithLength = Encoding.UTF8.GetString(buffer, 1, firstRcv - 1);
                            recStr = fileNameWithLength.Split('-').First();
                            fileLength = Convert.ToInt64(fileNameWithLength.Split('-').Last());
                        }
                    }
                }
                catch (Exception ex)
                {
                    Message.AppendText("系统异常..." + ex.Message);
                    break;
                }
            }
        }

        private void ServerSend(string SendStr,byte symbol)
        {
            //用UTF8能接受文字信息
            byte[] buffer = Encoding.UTF8.GetBytes(SendStr);
            //实际发送的字节数组比实际输入的长度多1,用于存取标识符
            byte[] newBuffer = new byte[buffer.Length+1];
            //标识符添加在位置为0的地方
            newBuffer[0] = symbol;
            Buffer.BlockCopy(buffer,0,newBuffer,1,buffer.Length);
            socketConnect.Send(newBuffer);
            Message.AppendText("PYT: "+ GetTime() + "\r\n" + SendStr+"\r\n");
        }

        string filePath = null;
        string fileName = null;

        private void Select_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofDialog = new OpenFileDialog();
            if(ofDialog.ShowDialog(this) == DialogResult.OK)
            {
                fileName = ofDialog.SafeFileName;//获取选取文件的文件名
                File.Text = fileName;//将文件名显示在文本框上
                filePath = ofDialog.FileName;//获取包含文件名的全路径
            }
        }

        private void SendFile(string fileFullPath)
        {
            if (string.IsNullOrEmpty(fileFullPath))
            {
                MessageBox.Show(@"请选择需要发送的文件!");
                return;
            }

            //发送文件前,将文件名和长度发过去
            long fileLength = new FileInfo(fileFullPath).Length;
            string totalMsg = string.Format("{0}-{1}", fileName, fileLength);
            ServerSend(totalMsg, 2);

            byte[] buffer = new byte[8*1024];

            using (FileStream fs = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read))
            {
                int readLength = 0;
                bool firstRead = true;
                long sentFileLength = 0;
                while ((readLength = fs.Read(buffer, 0, buffer.Length)) > 0 && sentFileLength < fileLength)
                {
                    sentFileLength += readLength;
                    //第一次发送的字节流上加个前缀1
                    if (firstRead)
                    {
                        byte[] firstBuffer = new byte[readLength + 1];
                        //标记1,代表为文件
                        firstBuffer[0] = 1;
                        Buffer.BlockCopy(buffer, 0, firstBuffer, 1, readLength);

                        socketConnect.Send(firstBuffer, 0, readLength + 1, SocketFlags.None);

                        firstRead = false;
                        continue;
                    }
                    socketConnect.Send(buffer, 0, readLength, SocketFlags.None);
                }
                fs.Close();
            }
            Message.AppendText("SoFlash:" + GetTime() + "\r\n您发送了文件:" + fileName + "\r\n");
        }

        private void Send_Click(object sender, EventArgs e)
        {
            ServerSend(SendMsg.Text,0);
        }

        private void SendMsg_keyDown(object sender, KeyEventArgs e)//Enter发送
        {
            if (e.KeyCode == Keys.Enter)
            {
                ServerSend(SendMsg.Text,0);
            }
        }

        private void Sendfile_Click(object sender, EventArgs e)
        {
            SendFile(filePath);
        }

        public DateTime GetTime()//获取系统时间
        {
            DateTime now = new DateTime();
            now = DateTime.Now;
            return now;
        }  

    }
}

客户端:



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;

namespace EasyChats
{
    public partial class Client : Form
    {
        public Client()
        {
            InitializeComponent();
            TextBox.CheckForIllegalCrossThreadCalls = false;
        }

        private void Client_Load(object sender, EventArgs e)
        {
            textIP.AppendText("127.0.0.1");
            textPort.AppendText("5555");
        }

        Socket socketClient = null;
        Thread threadClient = null;

        private void BeginClient_Click(object sender, EventArgs e)
        {
            socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            int port = Convert.ToInt32(textPort.Text.Trim());
            IPAddress ip = IPAddress.Parse(textIP.Text.Trim());
            IPEndPoint ipe = new IPEndPoint(ip, port);
            socketClient.Connect(ipe);
            threadClient = new Thread(RecMsg);
            threadClient.IsBackground = true;
            threadClient.Start();
            Message.AppendText("已经与服务端建立连接,可以开始通信...\r\n");
        }

        private void RecMsg()
        {
            long fileLength = 0;
            string recStr = null;
            while (true)
            {
                int firstRcv = 0;
                byte[] buffer = new byte[8 * 1024];
                try
                {
                    if (socketClient != null) firstRcv = socketClient.Receive(buffer);

                    if (firstRcv > 0)
                    {
                        if (buffer[0] == 0)
                        {
                            recStr = Encoding.UTF8.GetString(buffer, 1, firstRcv - 1);
                            Message.AppendText("PYT: " + GetTime() + "\r\n" + recStr + "\r\n");
                        }

                        if (buffer[0] == 1)
                        {
                            string filenameSuffix = recStr.Substring(recStr.LastIndexOf("."));
                            SaveFileDialog sfDialog = new SaveFileDialog()
                            {
                                Filter = "(*" + filenameSuffix + ")|*" + filenameSuffix + "",
                                FileName = recStr
                            };

                            if (sfDialog.ShowDialog(this) == DialogResult.OK)
                            {
                                string savePath = sfDialog.FileName;
                                int rec = 0;
                                long recFileLength = 0;
                                bool firstWrite = true;
                                using (FileStream fs = new FileStream(savePath, FileMode.Create, FileAccess.Write))
                                {
                                    while (recFileLength < fileLength)
                                    {
                                        if (firstWrite)
                                        {
                                            fs.Write(buffer, 1, firstRcv - 1);
                                            fs.Flush();
                                            recFileLength += firstRcv - 1;
                                            firstWrite = false;
                                        }
                                        else
                                        {
                                            rec = socketClient.Receive(buffer);
                                            fs.Write(buffer, 0, rec);
                                            fs.Flush();
                                            recFileLength += rec;
                                        }
                                    }
                                    fs.Close();
                                }

                                string fName = savePath.Substring(savePath.LastIndexOf("\\") + 1);
                                string fPath = savePath.Substring(0, savePath.LastIndexOf("\\"));
                                Message.AppendText("ZXY: " + GetTime() + "\r\n你成功接收了文件..." + fName + "\r\n保存路径为:" + fPath + "\r\n");
                            }
                        }
                        if (buffer[0] == 2)
                        {
                            string fileNameWithLength = Encoding.UTF8.GetString(buffer, 1, firstRcv - 1);
                            recStr = fileNameWithLength.Split('-').First();
                            fileLength = Convert.ToInt64(fileNameWithLength.Split('-').Last());
                        }
                    }
                }
                catch (Exception ex)
                {
                    Message.AppendText("系统异常..." + ex.Message);
                    break;
                }
            }
        }


        private void ClientSend(string SendStr, byte symbol)
        {
            byte[] buffer = Encoding.UTF8.GetBytes(SendStr);
            byte[] newBuffer = new byte[buffer.Length + 1];
            newBuffer[0] = symbol;
            Buffer.BlockCopy(buffer, 0, newBuffer, 1, buffer.Length);
            socketClient.Send(newBuffer);
            Message.AppendText("ZXY: " + GetTime() + "\r\n" + SendStr + "\r\n");
        }

        private void Send_Click_1(object sender, EventArgs e)
        {
            ClientSend(SendMsg.Text, 0);
        }

        string filePath = null;
        string fileName = null;

        private void fileSelect_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofDialog = new OpenFileDialog();
            if (ofDialog.ShowDialog(this) == DialogResult.OK)
            {
                fileName = ofDialog.SafeFileName;
                FileName.Text = fileName;
                filePath = ofDialog.FileName;
            }
        }

        private void fileSend_Click(object sender, EventArgs e)
        {
            SendFile(filePath);
        }

        private void SendFile(string fileFullPath)
        {
            if (string.IsNullOrEmpty(fileFullPath))
            {
                MessageBox.Show(@"请选择需要发送的文件...");
                return;
            }

            long fileLength = new FileInfo(fileFullPath).Length;
            string totalMsg = string.Format("{0}-{1}", fileName, fileLength);
            ClientSend(totalMsg, 2);

            byte[] buffer = new byte[2 * 1024];
            using (FileStream fs = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read))
            {
                int readLength = 0;
                bool firstRead = true;
                long sentFileLength = 0;
                while ((readLength = fs.Read(buffer, 0, buffer.Length)) > 0 && sentFileLength < fileLength)
                {
                    sentFileLength += readLength;
                    if (firstRead)
                    {
                        byte[] firstBuffer = new byte[readLength + 1];
                        firstBuffer[0] = 1;
                        Buffer.BlockCopy(buffer, 0, firstBuffer, 1, readLength);

                        socketClient.Send(firstBuffer, 0, readLength + 1, SocketFlags.None);

                        firstRead = false;
                    }
                    else
                    {
                        socketClient.Send(buffer, 0, readLength, SocketFlags.None);
                    }
                }
                fs.Close();
            }
            Message.AppendText("ZXY:" + GetTime() + "\r\n你发送了文件:" + fileName + "\r\n");
        }

        private void Send_Click(object sender, EventArgs e)
        {
            ClientSend(SendMsg.Text, 0);
        }



        private void SendMsg_keyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                ClientSend(SendMsg.Text, 0);
            }
        }

        private void Sendfile_Click(object sender, EventArgs e)
        {
            SendFile(filePath);
        }

        public DateTime GetTime()
        {
            DateTime now = new DateTime();
            now = DateTime.Now;
            return now;
        }


    }
}


对于线程的IsBackground的理解,摘自于网络:

1、当在主线程中创建了一个线程,那么该线程的IsBackground默认是设置为FALSE的。
2、当主线程退出的时候,IsBackground=FALSE的线程还会继续执行下去,直到线程执行结束。
3、只有IsBackground=TRUE的线程才会随着主线程的退出而退出。
4、当初始化一个线程,把Thread.IsBackground=true的时候,指示该线程为后台线程。后台线程将会随着主线程的退出而退出。
5、原理:只要所有前台线程都终止后,CLR就会对每一个活在的后台线程调用Abort()来彻底终止应用程序。


  • 13
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值