C# 简单通信(实现文件传输)
2015-10-15 11:56
381 查看
之前写过一个简单通信传输,不过只有聊天的功能,现在实现了文件传输的功能,借鉴于网上一篇博客,不过他写的仅仅是客户端对于服务器发送文件,我稍微优化了这个功能,实现了,端与端之间信息的互发和文件的互发,感觉学习这些新的东西,还刚开始,进度很慢,很多东西都需要从新去学习,不过慢慢来!Fighting!!!
服务器:
客户端:
对于线程的IsBackground的理解,摘自于网络:
1、当在主线程中创建了一个线程,那么该线程的IsBackground默认是设置为FALSE的。
2、当主线程退出的时候,IsBackground=FALSE的线程还会继续执行下去,直到线程执行结束。
3、只有IsBackground=TRUE的线程才会随着主线程的退出而退出。
4、当初始化一个线程,把Thread.IsBackground=true的时候,指示该线程为后台线程。后台线程将会随着主线程的退出而退出。
5、原理:只要所有前台线程都终止后,CLR就会对每一个活在的后台线程调用Abort()来彻底终止应用程序。
服务器:
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您发送了文件 c415 :" + 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()来彻底终止应用程序。
相关文章推荐
- C#中using指令的几种用法
- C# Action 委托
- 不用IDE写C#的Hello World的方法
- C#委托使用详解(Delegates)
- C#运行时相互关系浅析
- C#进度条实现
- c# 关于浅拷贝和深拷贝
- 杨辉三角——C#语言
- C# Window编程随记——新建一个window项目
- 关于C#中get和set
- C#如何获取今天是几月几号星期几
- C# WPF 中用代码模拟鼠标和键盘的操作
- C#中的结构体与类的区别
- c#相关连接
- C#流OffsetStream.cs扩展.net压缩库SharpCompress
- C#中的DataSet添加DataTable问题
- C# using 三种使用方式
- 【C#】获取本地Cookie的问题
- C#读取设置Cookie
- c#中Invoke方法