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


    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.  
    15. namespace EasyChat

    16. {

    17. public partial class Server : Form

    18. {

    19. public Server()

    20. {

    21. InitializeComponent();

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

    23. TextBox.CheckForIllegalCrossThreadCalls = false;

    24. }

    25.  
    26. private void Server_Load(object sender, EventArgs e)

    27. {

    28. textIP.AppendText("127.0.0.1");

    29. textPORT.AppendText("5555");

    30. }

    31.  
    32. Thread threadWatch = null;

    33. Socket socketWatch = null;

    34.  
    35.  
    36. private void ServerBegin_Click(object sender, EventArgs e)

    37. {

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

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

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

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

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

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

    44. socketWatch.Bind(ipe);

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

    46. //负责监听的线程

    47. threadWatch = new Thread(WatchConnect);

    48. //。。。

    49. threadWatch.IsBackground = true;

    50. threadWatch.Start();

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

    52. }

    53.  
    54. Socket socketConnect = null;

    55.  
    56. private void WatchConnect()

    57. {

    58. while (true)

    59. {

    60. try

    61. {

    62. socketConnect = socketWatch.Accept();

    63. }

    64. catch (Exception ex)

    65. {

    66. Message.AppendText(ex.Message);

    67. break;

    68. }

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

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

    71. ParameterizedThreadStart pts = new ParameterizedThreadStart(ServerRec);

    72. Thread thr = new Thread(pts);

    73. thr.Start(socketConnect);

    74. }

    75. }

    76.  
    77. string recStr = null;

    78. private void ServerRec(object obj)

    79. {

    80. Socket socketServer = obj as Socket;

    81. long fileLength = 0;

    82.  
    83. while (true)

    84. {

    85. int firstRcv = 0;

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

    87. try

    88. {

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

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

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

    93. {

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

    95. {

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

    97. Message.AppendText("ZXY: " + GetTime() + " " + recStr + " ");

    98. }

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

    101. {

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

    103. SaveFileDialog sfDialog = new SaveFileDialog()

    104. {

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

    106. FileName = recStr

    107. };

    108.  
    109. if (sfDialog.ShowDialog(this) == DialogResult.OK)

    110. {

    111. string savePath = sfDialog.FileName;

    112. int rec = 0;

    113. long recFileLength = 0;

    114. bool firstWrite = true;

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

    116. {

    117. while (recFileLength < fileLength)

    118. {

    119. if (firstWrite)

    120. {

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

    122. fs.Flush();

    123. recFileLength += firstRcv - 1;

    124. firstWrite = false;

    125. }

    126. else

    127. {

    128. rec = socketServer.Receive(buffer);

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

    130. fs.Flush();

    131. recFileLength += rec;

    132. }

    133. }

    134. fs.Close();

    135. }

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

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

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

    140. }

    141. }

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

    143. {

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

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

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

    147. }

    148. }

    149. }

    150. catch (Exception ex)

    151. {

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

    153. break;

    154. }

    155. }

    156. }

    157.  
    158. private void ServerSend(string SendStr,byte symbol)

    159. {

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

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

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

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

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

    165. newBuffer[0] = symbol;

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

    167. socketConnect.Send(newBuffer);

    168. Message.AppendText("PYT: "+ GetTime() + " " + SendStr+" ");

    169. }

    170.  
    171. string filePath = null;

    172. string fileName = null;

    173.  
    174. private void Select_Click(object sender, EventArgs e)

    175. {

    176. OpenFileDialog ofDialog = new OpenFileDialog();

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

    178. {

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

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

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

    182. }

    183. }

    184.  
    185. private void SendFile(string fileFullPath)

    186. {

    187. if (string.IsNullOrEmpty(fileFullPath))

    188. {

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

    190. return;

    191. }

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

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

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

    196. ServerSend(totalMsg, 2);

    197.  
    198. byte[] buffer = new byte[8*1024];

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

    201. {

    202. int readLength = 0;

    203. bool firstRead = true;

    204. long sentFileLength = 0;

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

    206. {

    207. sentFileLength += readLength;

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

    209. if (firstRead)

    210. {

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

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

    213. firstBuffer[0] = 1;

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

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

    217.  
    218. firstRead = false;

    219. continue;

    220. }

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

    222. }

    223. fs.Close();

    224. }

    225. Message.AppendText("SoFlash:" + GetTime() + " 您发送了文件:" + fileName + " ");

    226. }

    227.  
    228. private void Send_Click(object sender, EventArgs e)

    229. {

    230. ServerSend(SendMsg.Text,0);

    231. }

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

    234. {

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

    236. {

    237. ServerSend(SendMsg.Text,0);

    238. }

    239. }

    240.  
    241. private void Sendfile_Click(object sender, EventArgs e)

    242. {

    243. SendFile(filePath);

    244. }

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

    247. {

    248. DateTime now = new DateTime();

    249. now = DateTime.Now;

    250. return now;

    251. }

    252.  
    253. }

    254. }


    客户端:

     
    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.  
    15. namespace EasyChats

    16. {

    17. public partial class Client : Form

    18. {

    19. public Client()

    20. {

    21. InitializeComponent();

    22. TextBox.CheckForIllegalCrossThreadCalls = false;

    23. }

    24.  
    25. private void Client_Load(object sender, EventArgs e)

    26. {

    27. textIP.AppendText("127.0.0.1");

    28. textPort.AppendText("5555");

    29. }

    30.  
    31. Socket socketClient = null;

    32. Thread threadClient = null;

    33.  
    34. private void BeginClient_Click(object sender, EventArgs e)

    35. {

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

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

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

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

    40. socketClient.Connect(ipe);

    41. threadClient = new Thread(RecMsg);

    42. threadClient.IsBackground = true;

    43. threadClient.Start();

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

    45. }

    46.  
    47. private void RecMsg()

    48. {

    49. long fileLength = 0;

    50. string recStr = null;

    51. while (true)

    52. {

    53. int firstRcv = 0;

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

    55. try

    56. {

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

    58.  
    59. if (firstRcv > 0)

    60. {

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

    62. {

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

    64. Message.AppendText("PYT: " + GetTime() + " " + recStr + " ");

    65. }

    66.  
    67. if (buffer[0] == 1)

    68. {

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

    70. SaveFileDialog sfDialog = new SaveFileDialog()

    71. {

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

    73. FileName = recStr

    74. };

    75.  
    76. if (sfDialog.ShowDialog(this) == DialogResult.OK)

    77. {

    78. string savePath = sfDialog.FileName;

    79. int rec = 0;

    80. long recFileLength = 0;

    81. bool firstWrite = true;

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

    83. {

    84. while (recFileLength < fileLength)

    85. {

    86. if (firstWrite)

    87. {

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

    89. fs.Flush();

    90. recFileLength += firstRcv - 1;

    91. firstWrite = false;

    92. }

    93. else

    94. {

    95. rec = socketClient.Receive(buffer);

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

    97. fs.Flush();

    98. recFileLength += rec;

    99. }

    100. }

    101. fs.Close();

    102. }

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

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

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

    107. }

    108. }

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

    110. {

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

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

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

    114. }

    115. }

    116. }

    117. catch (Exception ex)

    118. {

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

    120. break;

    121. }

    122. }

    123. }

    124.  
    125.  
    126. private void ClientSend(string SendStr, byte symbol)

    127. {

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

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

    130. newBuffer[0] = symbol;

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

    132. socketClient.Send(newBuffer);

    133. Message.AppendText("ZXY: " + GetTime() + " " + SendStr + " ");

    134. }

    135.  
    136. private void Send_Click_1(object sender, EventArgs e)

    137. {

    138. ClientSend(SendMsg.Text, 0);

    139. }

    140.  
    141. string filePath = null;

    142. string fileName = null;

    143.  
    144. private void fileSelect_Click(object sender, EventArgs e)

    145. {

    146. OpenFileDialog ofDialog = new OpenFileDialog();

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

    148. {

    149. fileName = ofDialog.SafeFileName;

    150. FileName.Text = fileName;

    151. filePath = ofDialog.FileName;

    152. }

    153. }

    154.  
    155. private void fileSend_Click(object sender, EventArgs e)

    156. {

    157. SendFile(filePath);

    158. }

    159.  
    160. private void SendFile(string fileFullPath)

    161. {

    162. if (string.IsNullOrEmpty(fileFullPath))

    163. {

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

    165. return;

    166. }

    167.  
    168. long fileLength = new FileInfo(fileFullPath).Length;

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

    170. ClientSend(totalMsg, 2);

    171.  
    172. byte[] buffer = new byte[2 * 1024];

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

    174. {

    175. int readLength = 0;

    176. bool firstRead = true;

    177. long sentFileLength = 0;

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

    179. {

    180. sentFileLength += readLength;

    181. if (firstRead)

    182. {

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

    184. firstBuffer[0] = 1;

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

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

    188.  
    189. firstRead = false;

    190. }

    191. else

    192. {

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

    194. }

    195. }

    196. fs.Close();

    197. }

    198. Message.AppendText("ZXY:" + GetTime() + " 你发送了文件:" + fileName + " ");

    199. }

    200.  
    201. private void Send_Click(object sender, EventArgs e)

    202. {

    203. ClientSend(SendMsg.Text, 0);

    204. }

    205.  
    206.  
    207.  
    208. private void SendMsg_keyDown(object sender, KeyEventArgs e)

    209. {

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

    211. {

    212. ClientSend(SendMsg.Text, 0);

    213. }

    214. }

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

    217. {

    218. SendFile(filePath);

    219. }

    220.  
    221. public DateTime GetTime()

    222. {

    223. DateTime now = new DateTime();

    224. now = DateTime.Now;

    225. return now;

    226. }

    227.  
    228.  
    229. }

    230. }

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

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

  • 相关阅读:
    Atitit sql计划任务与查询优化器统计信息模块
    Atitit  数据库的事件机制触发器与定时任务attilax总结
    Atitit 图像处理知识点体系知识图谱 路线图attilax总结 v4 qcb.xlsx
    Atitit 图像处理 深刻理解梯度原理计算.v1 qc8
    Atiti 数据库系统原理 与数据库方面的书籍 attilax总结 v3 .docx
    Atitit Mysql查询优化器 存取类型 范围存取类型 索引存取类型 AND or的分析
    Atitit View事件分发机制
    Atitit 基于sql编程语言的oo面向对象大规模应用解决方案attilax总结
    Atitti 存储引擎支持的国内点与特性attilax总结
    Atitit 深入理解软件的本质 attilax总结 软件三原则"三次原则"是DRY原则和YAGNI原则的折
  • 原文地址:https://www.cnblogs.com/zkwarrior/p/11759276.html
Copyright © 2020-2023  润新知