https://blog.csdn.net/Sayesan/article/details/82185772

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

服务器:

 
  1. using System;

  2. using System.Collections.Generic;

  3. using System.ComponentModel;

  4. using System.Data;

  5. using System.Drawing;

  6. using System.Linq;

  7. using System.Text;

  8. using System.Threading.Tasks;

  9. using System.Windows.Forms;

  10. using System.Net;

  11. using System.Net.Sockets;

  12. using System.Threading;

  13. using System.IO;

  14. namespace EasyChat

  15. {

  16. public partial class Server : Form

  17. {

  18. public Server()

  19. {

  20. InitializeComponent();

  21. //关闭对文本框的非法线程操作检查

  22. TextBox.CheckForIllegalCrossThreadCalls = false;

  23. }

  24. private void Server_Load(object sender, EventArgs e)

  25. {

  26. textIP.AppendText("127.0.0.1");

  27. textPORT.AppendText("5555");

  28. }

  29. Thread threadWatch = null;

  30. Socket socketWatch = null;

  31. private void ServerBegin_Click(object sender, EventArgs e)

  32. {

  33. //定义一个套接字,监听发来的信息,包含3个参数(IP4寻址协议,流式连接,TCP协议)

  34. socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

  35. int port = Convert.ToInt32(textPORT.Text.Trim());

  36. IPAddress ip = IPAddress.Parse(textIP.Text.Trim());

  37. //绑定IP地址和端口号

  38. IPEndPoint ipe = new IPEndPoint(ip, port);

  39. socketWatch.Bind(ipe);

  40. socketWatch.Listen(20);//监听队列长度,20

  41. //负责监听的线程

  42. threadWatch = new Thread(WatchConnect);

  43. //。。。

  44. threadWatch.IsBackground = true;

  45. threadWatch.Start();

  46. Message.AppendText("服务器已经启动,开始监听..."+"\r\n");

  47. }

  48. Socket socketConnect = null;

  49. private void WatchConnect()

  50. {

  51. while (true)

  52. {

  53. try

  54. {

  55. socketConnect = socketWatch.Accept();

  56. }

  57. catch (Exception ex)

  58. {

  59. Message.AppendText(ex.Message);

  60. break;

  61. }

  62. Message.AppendText("客户端连接成功,可以开始通信..."+"\r\n");

  63. //创建通信线程,感觉这个和Thread的区别,就是这个有参,另一个无参

  64. ParameterizedThreadStart pts = new ParameterizedThreadStart(ServerRec);

  65. Thread thr = new Thread(pts);

  66. thr.Start(socketConnect);

  67. }

  68. }

  69. string recStr = null;

  70. private void ServerRec(object obj)

  71. {

  72. Socket socketServer = obj as Socket;

  73. long fileLength = 0;

  74. while (true)

  75. {

  76. int firstRcv = 0;

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

  78. try

  79. {

  80. //获取接受数据的长度,存入内存缓冲区,返回一个字节数组的长度

  81. if (socketServer != null) firstRcv = socketServer.Receive(buffer);

  82. if (firstRcv > 0)//大于0,说明有东西传过来

  83. {

  84. if (buffer[0] == 0)//0对应文字信息

  85. {

  86. recStr = Encoding.UTF8.GetString(buffer, 1, firstRcv - 1);

  87. Message.AppendText("ZXY: " + GetTime() + "\r\n" + recStr + "\r\n");

  88. }

  89. if (buffer[0] == 1)//1对应文件信息

  90. {

  91. string filenameSuffix = recStr.Substring(recStr.LastIndexOf("."));

  92. SaveFileDialog sfDialog = new SaveFileDialog()

  93. {

  94. Filter = "(*" + filenameSuffix + ")|*" + filenameSuffix + "",

  95. FileName = recStr

  96. };

  97. if (sfDialog.ShowDialog(this) == DialogResult.OK)

  98. {

  99. string savePath = sfDialog.FileName;

  100. int rec = 0;

  101. long recFileLength = 0;

  102. bool firstWrite = true;

  103. using (FileStream fs = new FileStream(savePath, FileMode.Create, FileAccess.Write))

  104. {

  105. while (recFileLength < fileLength)

  106. {

  107. if (firstWrite)

  108. {

  109. fs.Write(buffer, 1, firstRcv - 1);

  110. fs.Flush();

  111. recFileLength += firstRcv - 1;

  112. firstWrite = false;

  113. }

  114. else

  115. {

  116. rec = socketServer.Receive(buffer);

  117. fs.Write(buffer, 0, rec);

  118. fs.Flush();

  119. recFileLength += rec;

  120. }

  121. }

  122. fs.Close();

  123. }

  124. string fName = savePath.Substring(savePath.LastIndexOf("\\") + 1);

  125. string fPath = savePath.Substring(0, savePath.LastIndexOf("\\"));

  126. Message.AppendText("ZXY: " + GetTime() + "\r\n你成功接收了文件..." + fName + "\r\n保存路径为:" + fPath + "\r\n");

  127. }

  128. }

  129. if (buffer[0] == 2)//2对应文件名字和长度

  130. {

  131. string fileNameWithLength = Encoding.UTF8.GetString(buffer, 1, firstRcv - 1);

  132. recStr = fileNameWithLength.Split('-').First();

  133. fileLength = Convert.ToInt64(fileNameWithLength.Split('-').Last());

  134. }

  135. }

  136. }

  137. catch (Exception ex)

  138. {

  139. Message.AppendText("系统异常..." + ex.Message);

  140. break;

  141. }

  142. }

  143. }

  144. private void ServerSend(string SendStr,byte symbol)

  145. {

  146. //用UTF8能接受文字信息

  147. byte[] buffer = Encoding.UTF8.GetBytes(SendStr);

  148. //实际发送的字节数组比实际输入的长度多1,用于存取标识符

  149. byte[] newBuffer = new byte[buffer.Length+1];

  150. //标识符添加在位置为0的地方

  151. newBuffer[0] = symbol;

  152. Buffer.BlockCopy(buffer,0,newBuffer,1,buffer.Length);

  153. socketConnect.Send(newBuffer);

  154. Message.AppendText("PYT: "+ GetTime() + "\r\n" + SendStr+"\r\n");

  155. }

  156. string filePath = null;

  157. string fileName = null;

  158. private void Select_Click(object sender, EventArgs e)

  159. {

  160. OpenFileDialog ofDialog = new OpenFileDialog();

  161. if(ofDialog.ShowDialog(this) == DialogResult.OK)

  162. {

  163. fileName = ofDialog.SafeFileName;//获取选取文件的文件名

  164. File.Text = fileName;//将文件名显示在文本框上

  165. filePath = ofDialog.FileName;//获取包含文件名的全路径

  166. }

  167. }

  168. private void SendFile(string fileFullPath)

  169. {

  170. if (string.IsNullOrEmpty(fileFullPath))

  171. {

  172. MessageBox.Show(@"请选择需要发送的文件!");

  173. return;

  174. }

  175. //发送文件前,将文件名和长度发过去

  176. long fileLength = new FileInfo(fileFullPath).Length;

  177. string totalMsg = string.Format("{0}-{1}", fileName, fileLength);

  178. ServerSend(totalMsg, 2);

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

  180. using (FileStream fs = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read))

  181. {

  182. int readLength = 0;

  183. bool firstRead = true;

  184. long sentFileLength = 0;

  185. while ((readLength = fs.Read(buffer, 0, buffer.Length)) > 0 && sentFileLength < fileLength)

  186. {

  187. sentFileLength += readLength;

  188. //第一次发送的字节流上加个前缀1

  189. if (firstRead)

  190. {

  191. byte[] firstBuffer = new byte[readLength + 1];

  192. //标记1,代表为文件

  193. firstBuffer[0] = 1;

  194. Buffer.BlockCopy(buffer, 0, firstBuffer, 1, readLength);

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

  196. firstRead = false;

  197. continue;

  198. }

  199. socketConnect.Send(buffer, 0, readLength, SocketFlags.None);

  200. }

  201. fs.Close();

  202. }

  203. Message.AppendText("SoFlash:" + GetTime() + "\r\n您发送了文件:" + fileName + "\r\n");

  204. }

  205. private void Send_Click(object sender, EventArgs e)

  206. {

  207. ServerSend(SendMsg.Text,0);

  208. }

  209. private void SendMsg_keyDown(object sender, KeyEventArgs e)//Enter发送

  210. {

  211. if (e.KeyCode == Keys.Enter)

  212. {

  213. ServerSend(SendMsg.Text,0);

  214. }

  215. }

  216. private void Sendfile_Click(object sender, EventArgs e)

  217. {

  218. SendFile(filePath);

  219. }

  220. public DateTime GetTime()//获取系统时间

  221. {

  222. DateTime now = new DateTime();

  223. now = DateTime.Now;

  224. return now;

  225. }

  226. }

  227. }

客户端:

 
  1. using System;

  2. using System.Collections.Generic;

  3. using System.ComponentModel;

  4. using System.Data;

  5. using System.Drawing;

  6. using System.Linq;

  7. using System.Text;

  8. using System.Threading.Tasks;

  9. using System.Windows.Forms;

  10. using System.Net;

  11. using System.Net.Sockets;

  12. using System.Threading;

  13. using System.IO;

  14. namespace EasyChats

  15. {

  16. public partial class Client : Form

  17. {

  18. public Client()

  19. {

  20. InitializeComponent();

  21. TextBox.CheckForIllegalCrossThreadCalls = false;

  22. }

  23. private void Client_Load(object sender, EventArgs e)

  24. {

  25. textIP.AppendText("127.0.0.1");

  26. textPort.AppendText("5555");

  27. }

  28. Socket socketClient = null;

  29. Thread threadClient = null;

  30. private void BeginClient_Click(object sender, EventArgs e)

  31. {

  32. socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

  33. int port = Convert.ToInt32(textPort.Text.Trim());

  34. IPAddress ip = IPAddress.Parse(textIP.Text.Trim());

  35. IPEndPoint ipe = new IPEndPoint(ip, port);

  36. socketClient.Connect(ipe);

  37. threadClient = new Thread(RecMsg);

  38. threadClient.IsBackground = true;

  39. threadClient.Start();

  40. Message.AppendText("已经与服务端建立连接,可以开始通信...\r\n");

  41. }

  42. private void RecMsg()

  43. {

  44. long fileLength = 0;

  45. string recStr = null;

  46. while (true)

  47. {

  48. int firstRcv = 0;

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

  50. try

  51. {

  52. if (socketClient != null) firstRcv = socketClient.Receive(buffer);

  53. if (firstRcv > 0)

  54. {

  55. if (buffer[0] == 0)

  56. {

  57. recStr = Encoding.UTF8.GetString(buffer, 1, firstRcv - 1);

  58. Message.AppendText("PYT: " + GetTime() + "\r\n" + recStr + "\r\n");

  59. }

  60. if (buffer[0] == 1)

  61. {

  62. string filenameSuffix = recStr.Substring(recStr.LastIndexOf("."));

  63. SaveFileDialog sfDialog = new SaveFileDialog()

  64. {

  65. Filter = "(*" + filenameSuffix + ")|*" + filenameSuffix + "",

  66. FileName = recStr

  67. };

  68. if (sfDialog.ShowDialog(this) == DialogResult.OK)

  69. {

  70. string savePath = sfDialog.FileName;

  71. int rec = 0;

  72. long recFileLength = 0;

  73. bool firstWrite = true;

  74. using (FileStream fs = new FileStream(savePath, FileMode.Create, FileAccess.Write))

  75. {

  76. while (recFileLength < fileLength)

  77. {

  78. if (firstWrite)

  79. {

  80. fs.Write(buffer, 1, firstRcv - 1);

  81. fs.Flush();

  82. recFileLength += firstRcv - 1;

  83. firstWrite = false;

  84. }

  85. else

  86. {

  87. rec = socketClient.Receive(buffer);

  88. fs.Write(buffer, 0, rec);

  89. fs.Flush();

  90. recFileLength += rec;

  91. }

  92. }

  93. fs.Close();

  94. }

  95. string fName = savePath.Substring(savePath.LastIndexOf("\\") + 1);

  96. string fPath = savePath.Substring(0, savePath.LastIndexOf("\\"));

  97. Message.AppendText("ZXY: " + GetTime() + "\r\n你成功接收了文件..." + fName + "\r\n保存路径为:" + fPath + "\r\n");

  98. }

  99. }

  100. if (buffer[0] == 2)

  101. {

  102. string fileNameWithLength = Encoding.UTF8.GetString(buffer, 1, firstRcv - 1);

  103. recStr = fileNameWithLength.Split('-').First();

  104. fileLength = Convert.ToInt64(fileNameWithLength.Split('-').Last());

  105. }

  106. }

  107. }

  108. catch (Exception ex)

  109. {

  110. Message.AppendText("系统异常..." + ex.Message);

  111. break;

  112. }

  113. }

  114. }

  115. private void ClientSend(string SendStr, byte symbol)

  116. {

  117. byte[] buffer = Encoding.UTF8.GetBytes(SendStr);

  118. byte[] newBuffer = new byte[buffer.Length + 1];

  119. newBuffer[0] = symbol;

  120. Buffer.BlockCopy(buffer, 0, newBuffer, 1, buffer.Length);

  121. socketClient.Send(newBuffer);

  122. Message.AppendText("ZXY: " + GetTime() + "\r\n" + SendStr + "\r\n");

  123. }

  124. private void Send_Click_1(object sender, EventArgs e)

  125. {

  126. ClientSend(SendMsg.Text, 0);

  127. }

  128. string filePath = null;

  129. string fileName = null;

  130. private void fileSelect_Click(object sender, EventArgs e)

  131. {

  132. OpenFileDialog ofDialog = new OpenFileDialog();

  133. if (ofDialog.ShowDialog(this) == DialogResult.OK)

  134. {

  135. fileName = ofDialog.SafeFileName;

  136. FileName.Text = fileName;

  137. filePath = ofDialog.FileName;

  138. }

  139. }

  140. private void fileSend_Click(object sender, EventArgs e)

  141. {

  142. SendFile(filePath);

  143. }

  144. private void SendFile(string fileFullPath)

  145. {

  146. if (string.IsNullOrEmpty(fileFullPath))

  147. {

  148. MessageBox.Show(@"请选择需要发送的文件...");

  149. return;

  150. }

  151. long fileLength = new FileInfo(fileFullPath).Length;

  152. string totalMsg = string.Format("{0}-{1}", fileName, fileLength);

  153. ClientSend(totalMsg, 2);

  154. byte[] buffer = new byte[2 * 1024];

  155. using (FileStream fs = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read))

  156. {

  157. int readLength = 0;

  158. bool firstRead = true;

  159. long sentFileLength = 0;

  160. while ((readLength = fs.Read(buffer, 0, buffer.Length)) > 0 && sentFileLength < fileLength)

  161. {

  162. sentFileLength += readLength;

  163. if (firstRead)

  164. {

  165. byte[] firstBuffer = new byte[readLength + 1];

  166. firstBuffer[0] = 1;

  167. Buffer.BlockCopy(buffer, 0, firstBuffer, 1, readLength);

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

  169. firstRead = false;

  170. }

  171. else

  172. {

  173. socketClient.Send(buffer, 0, readLength, SocketFlags.None);

  174. }

  175. }

  176. fs.Close();

  177. }

  178. Message.AppendText("ZXY:" + GetTime() + "\r\n你发送了文件:" + fileName + "\r\n");

  179. }

  180. private void Send_Click(object sender, EventArgs e)

  181. {

  182. ClientSend(SendMsg.Text, 0);

  183. }

  184. private void SendMsg_keyDown(object sender, KeyEventArgs e)

  185. {

  186. if (e.KeyCode == Keys.Enter)

  187. {

  188. ClientSend(SendMsg.Text, 0);

  189. }

  190. }

  191. private void Sendfile_Click(object sender, EventArgs e)

  192. {

  193. SendFile(filePath);

  194. }

  195. public DateTime GetTime()

  196. {

  197. DateTime now = new DateTime();

  198. now = DateTime.Now;

  199. return now;

  200. }

  201. }

  202. }

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

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

C# 简单通信(实现文件传输)的更多相关文章

  1. 基于UDT connect连接通信以及文件传输--服务端

    网上与UDT相关的资料不多,与UDT相关的源码例子更少.最近在接触UDT,也是因为缺少相关的资料,导致学习起来甚感痛苦.下面将我自己这两天弄出来的代码贴出来,希望对在寻找相关资料的童鞋有一定的帮助.与 ...

  2. 基于UDT connect连接通信以及文件传输--客户端

    上面一篇文章中提出了服务端的,其实这里没有严格意义的服务端和客户端之分,因为我在代码中是基于UDP的,不存在服务端与客户端,两个都是对等的,只是我这里进行一下简单的区分而已.在这里,客户端所进行的主要 ...

  3. NAT穿透进行P2P文件传输

    实现一个简单的p2p文件传输,主要解决NAT穿透问题,使用tcp协议传输. NAT背景介绍 简介 NAT(Network Address Translation ,网络地址转换) 是一种广泛应用的解决 ...

  4. QT从入门到入土(九)——TCP/IP网络通信(以及文件传输)

    引言 TCP/IP通信(即SOCKET通信)是通过网线将服务器Server端和客户机Client端进行连接,在遵循ISO/OSI模型的四层层级构架的基础上通过TCP/IP协议建立的通讯.控制器可以设置 ...

  5. 【RL-TCPnet网络教程】第38章 TFTP简单文件传输基础知识

    第38章      TFTP简单文件传输基础知识 本章节为大家讲解TFTP(Trivial File Transfer Protocol,简单文件传输协议)的基础知识,方便后面章节的实战操作. (本章 ...

  6. Python之路(第三十二篇) 网络编程:udp套接字、简单文件传输

    一.UDP套接字 服务端 # udp是无链接的,先启动哪一端都不会报错 # udp没有链接,与tcp相比没有链接循环,只有通讯循环 server = socket.socket(socket.AF_I ...

  7. 网络编程 - socket通信/粘包/文件传输/udp - 总结

    socket通信 1.简单的套接字通信 import socket phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.bin ...

  8. tftp简单文件传输协议搭建

    TFTP 简单文件传输协议     安装     sudo apt-get install tftp  tftpd openbsd-inetd     需要tftp tftpd openbsd-ine ...

  9. python 全栈开发,Day129(玩具开机提示语,为多个玩具发送点播,聊天界面,app录音,app与服务器端文件传输,简单的对话)

    一.玩具开机提示语 先下载github代码,下面的操作,都是基于这个版本来的! https://github.com/987334176/Intelligent_toy/archive/v1.2.zi ...

随机推荐

  1. orcale的to_number方法

    转自:https://blog.csdn.net/tiantangdizhibuxiang/article/details/81034893 TO_NUMBER函数()是Oracle中常用的类型转换函 ...

  2. SpringBoot2.x搭建SpringBootAdmin2.x

    1 说明 全部配置基于1.8.0_111 当前SpringBoot使用2.0.5 SpringBootAdmin基于Eureka进行Client发现,Eureka搭建参见SpringBoot2.x搭建 ...

  3. ansible(三)

    setup ansible_all_ipv4_addresses # ipv4的所有地址 ansible_all_ipv6_addresses # ipv6的所有地址 ansible_date_tim ...

  4. 浅析数据库(DB)、操作数据存储(ODS)和数据仓库(DW)的区别与联系

    文章背景: 相信大部分刚接触上面三个概念的同学,都多多少少会有些迷惑,现在我就给大家简单分析下这三者的关系,希望大家对这三者的概念理解有所帮助吧. 本文主要从下面两类关系来叙述上面三者的关系: 数据库 ...

  5. Controller的激活(1)

    Public interface IController { void Execute(RequestContext requestContext) } Public abstract Class C ...

  6. 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)

    题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9:  对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可.     后者mod=1e9,5才 ...

  7. python基础语法10 函数递归,模块,软件开发目录规范

    函数递归: 函数递归指的是重复 “直接调用或间接调用” 函数本身, 这是一种函数嵌套调用的表现形式. 直接调用: 指的是在函数内置,直接调用函数本身. 间接调用: 两个函数之间相互调用间接造成递归. ...

  8. oracle中删除表:drop、delete、truncate

    相同点,使用drop delete truncate 都会删除表中的内容 drop table 表名 delete from 表名(后面不跟where语句,则删除表中所有的数据) truncate t ...

  9. DSL的本质:领域构建的半成品

    DSL的本质是使用通用和专用语言构建领域的半成品: 实际上是构建了一个世界观.小宇宙的半成品: 这个半成品包含领域的基本要素.联系方式和基本运行规律: 开发者使用这个半成品平台进行开发能达到事半功倍. ...

  10. 编程语言的类型修饰符modifiers

    编程语言修饰符,代表语言要素与常规表达不同的语义: 这些语义的不同需要编译器和运行时作出不同的解释: 作用域.访问: 生命周期: 同步异步: 多态: 纯函数: 注解: 懒加载: 编译器合成: