C# 簡單通訊(支援一對多)
阿新 • • 發佈:2019-02-04
也就伺服器不一樣的寫法,弄了一個類似於Map的容器,其實是字典陣列的感覺,客戶端和原來一樣
服務端:
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 Server2 { public partial class Server : Form { public Server() { InitializeComponent(); TextBox.CheckForIllegalCrossThreadCalls = false; } Thread threadWatch = null; Socket socketWatch = null; private void SendServer_Click(object sender, EventArgs e) { socketWatch = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); int port = Convert.ToInt32(Port.Text.Trim()); IPAddress ip = IPAddress.Parse(IP.Text.Trim()); IPEndPoint ipe = new IPEndPoint(ip, port); socketWatch.Bind(ipe); socketWatch.Listen(5); threadWatch = new Thread(WatchConnect); threadWatch.IsBackground = true; threadWatch.Start(); Message.AppendText("伺服器已經啟動,開始監聽..." + "\r\n"); } //感覺和C++的Map一樣的一個容器 Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>(); Socket socketConnect = null;//與客戶端建立連線的套接字 string clientName = null;//訪問者的名字 IPAddress clientIP;//訪問者的IP int clientPort;//訪問者的埠號 private void WatchConnect() { while (true) { try { socketConnect = socketWatch.Accept(); } catch (Exception ex) { Message.AppendText(ex.Message); break; } clientIP = (socketConnect.RemoteEndPoint as IPEndPoint).Address;//獲取訪問者的IP clientPort = (socketConnect.RemoteEndPoint as IPEndPoint).Port;//獲取訪問者的Port //建立訪問者的標識,IP + Port clientName = "IP:" + clientIP + "Port:" + clientPort; ClientList.Items.Add(clientName);//在列表新增訪問者資訊 dicSocket.Add(clientName,socketConnect);//在字典資料中新增訪問者 ParameterizedThreadStart pts = new ParameterizedThreadStart(ServerRec); Thread thread = new Thread(pts); thread.IsBackground = true; thread.Start(socketConnect); Message.AppendText("IP:" + clientIP + " Port:" + clientPort + " 的客戶端與您連線成功,現在你們可以開始通訊了...\r\n"); } } 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(clientName + ": " + 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("你在: " + GetTime() + "\r\n你成功接收 " + clientName + "的檔案" + 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 SendMessage_Click(object sender, EventArgs e) { ServerSend(XiaoXi.Text,0); } 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); if (!string.IsNullOrEmpty(ClientList.Text.Trim())) { dicSocket[ClientList.Text.Trim()].Send(newBuffer); Message.AppendText("您在 " + GetTime() + " 向 IP: " + clientIP + " Port: " + clientPort + " 的客戶端傳送了:\r\n" + SendStr + "\r\n"); } else { for (int i = 0; i < ClientList.Items.Count; i++) { dicSocket[ClientList.Items[i].ToString()].Send(newBuffer); } Message.AppendText("您在 " + GetTime() + " 群發了資訊:\r\n" + SendStr + " \r\n"); } XiaoXi.Text = null; } string filePath = null; string fileName = null; private void SelectFile_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 SendFile_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); 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); if (!string.IsNullOrEmpty(ClientList.Text.Trim())) { dicSocket[ClientList.Text.Trim()].Send(firstBuffer, 0, readLength + 1, SocketFlags.None); Message.AppendText("您在 " + GetTime() + " 向 IP: " + clientIP + " Port: " + clientPort + " 的客戶端傳送了:\r\n" + fileName + "\r\n"); } else { for (int i = 0; i < ClientList.Items.Count; i++) { dicSocket[ClientList.Items[i].ToString()].Send(firstBuffer, 0, readLength + 1, SocketFlags.None); } Message.AppendText("您在 " + GetTime() + " 群發了檔案:\r\n" + fileName + " \r\n"); } FileName.Text = null; firstRead = false; continue; } if (!string.IsNullOrEmpty(ClientList.Text.Trim())) { dicSocket[ClientList.Text.Trim()].Send(buffer, 0, readLength + 1, SocketFlags.None); Message.AppendText("您在 " + GetTime() + " 向 IP: " + clientIP + " Port: " + clientPort + " 的客戶端傳送了:\r\n" + fileName + "\r\n"); } else { for (int i = 0; i < ClientList.Items.Count; i++) { dicSocket[ClientList.Items[i].ToString()].Send(buffer, 0, readLength + 1, SocketFlags.None); } Message.AppendText("您在 " + GetTime() + " 群發了檔案:\r\n" + fileName + " \r\n"); } FileName.Text = null; } fs.Close(); } } public DateTime GetTime()//獲取系統時間 { DateTime now = new DateTime(); now = DateTime.Now; return now; } private void Server_Load(object sender, EventArgs e) { IP.AppendText("127.0.0.1"); Port.AppendText("5555"); } private void choose_Click(object sender, EventArgs e) { ClientList.SelectedItem = null; } } }