• 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()来彻底终止应用程序。

  • 相关阅读:
    约束
    TCL(事务控制语言)
    MySQL常见约束
    “三大范式”及数据库设计
    同义词(别名)
    分享35个非常漂亮的单页网站设计案例
    Eclipse智能提示 (原创)
    java架构师之路:JAVA程序员必看的15本书的电子版下载地址
    Java初级学习笔记
    Java程序的汉化
  • 原文地址:https://www.cnblogs.com/zkwarrior/p/11759276.html
Copyright © 2020-2023  润新知