C# 簡單通訊(實現文件傳輸)

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

以前寫過一個簡單通訊傳輸,不過只有聊天的功能,如今實現了文件傳輸的功能,借鑑於網上一篇博客,不過他寫的僅僅是客戶端對於服務器發送文件,我稍微優化了這個功能,實現了,端與端之間信息的互發和文件的互發,感受學習這些新的東西,還剛開始,進度很慢,不少東西都須要重新去學習,不過慢慢來!Fighting!!!服務器

 

 

服務器:網絡

 

 

 
  1. using System;socket

  2. using System.Collections.Generic;學習

  3. using System.ComponentModel;優化

  4. using System.Data;this

  5. using System.Drawing;spa

  6. using System.Linq;.net

  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("服務器已經啓動,開始監聽..."+"\r\n");

  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("客戶端鏈接成功,能夠開始通訊..."+"\r\n");

  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() + "\r\n" + recStr + "\r\n");

  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() + "\r\n你成功接收了文件..." + fName + "\r\n保存路徑爲:" + fPath + "\r\n");

  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() + "\r\n" + SendStr+"\r\n");

  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() + "\r\n您發送了文件:" + fileName + "\r\n");

  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("已經與服務端創建鏈接,能夠開始通訊...\r\n");

  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() + "\r\n" + recStr + "\r\n");

  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() + "\r\n你成功接收了文件..." + fName + "\r\n保存路徑爲:" + fPath + "\r\n");

  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() + "\r\n" + SendStr + "\r\n");

  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() + "\r\n你發送了文件:" + fileName + "\r\n");

  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的理解,摘自於網絡:

一、當在主線程中建立了一個線程,那麼該線程的IsBackground默認是設置爲FALSE的。二、當主線程退出的時候,IsBackground=FALSE的線程還會繼續執行下去,直到線程執行結束。三、只有IsBackground=TRUE的線程纔會隨着主線程的退出而退出。四、當初始化一個線程,把Thread.IsBackground=true的時候,指示該線程爲後臺線程。後臺線程將會隨着主線程的退出而退出。五、原理:只要全部前臺線程都終止後,CLR就會對每個活在的後臺線程調用Abort()來完全終止應用程序。

相關文章
相關標籤/搜索