一、直接上效果圖
二、Socket握手
三、服務端
Thread threadWatch = null;// 負責監聽客戶端的線程 Socket socketWatch = null;// 負責監聽客戶端的套接字 Socket clientConnection = null;// 負責和客戶端通信的套接字 private void btn_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(ipAddress.Text.ToString())) { MessageBox.Show("監聽ip地址不能為空!"); return; } if (string.IsNullOrEmpty(port.Text.ToString())) { MessageBox.Show("監聽端口不能為空!"); return; } // 定義一個套接字用於監聽客戶端發來的消息,包含三個參數(ipv4尋址協議,流式連接,tcp協議) socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 服務端發送消息需要一個ip地址和端口號 IPAddress ip = IPAddress.Parse(ipAddress.Text.Trim()); // 把ip地址和端口號綁定在網路節點endport上 IPEndPoint endPort = new IPEndPoint(ip, int.Parse(port.Text.Trim())); // 監聽綁定的網路節點 socketWatch.Bind(endPort); // 將套接字的監聽隊列長度設置限制為0,0表示無限 socketWatch.Listen(0); // 創建一個監聽線程 threadWatch = new Thread(WatchConnecting); threadWatch.IsBackground = true; threadWatch.Start(); chatContent.AppendText("成功啟動監聽!ip:"+ip+",端口:"+port.Text.Trim()+"\r\n"); } /// <summary> /// 監聽客戶端發來的請求 /// </summary> private void WatchConnecting() { //持續不斷監聽客戶端發來的請求 while (true) { clientConnection = socketWatch.Accept(); chatContent.AppendText("客戶端連接成功!"+"\r\n"); // 創建一個通信線程 ParameterizedThreadStart pts = new ParameterizedThreadStart(acceptMsg); Thread thr = new Thread(pts); thr.IsBackground = true; thr.Start(clientConnection); } } /// <summary> /// 接收客戶端發來的消息 /// </summary> /// <param name="socket">客戶端套接字對象</param> private void acceptMsg(object socket) { Socket socketServer = socket as Socket; while (true) { //創建一個內存緩沖區 其大小為1024*1024字節 即1M byte[] recMsg = new byte[1024 * 1024]; //將接收到的信息存入到內存緩沖區,並返回其字節數組的長度 int length = socketServer.Receive(recMsg); //將機器接受到的字節數組轉換為人可以讀懂的字符串 string msg = Encoding.UTF8.GetString(recMsg,0,length); chatContent.AppendText("客戶端("+GetCurrentTime()+"):"+msg+"\r\n"); } } /// <summary> /// 發送消息到客戶端 /// </summary> /// <param name="msg"></param> private void serverSendMsg(string msg) { byte[] sendMsg = Encoding.UTF8.GetBytes(msg); clientConnection.Send(sendMsg); chatContent.AppendText("服務端("+GetCurrentTime()+"):"+msg+"\r\n"); } /// <summary> /// 獲取當前系統時間的方法 /// </summary> /// <returns>當前時間</returns> private DateTime GetCurrentTime() { DateTime currentTime = new DateTime(); currentTime = DateTime.Now; return currentTime; }
四、客戶端
// 創建一個客戶端套接字 Socket clientSocket = null; // 創建一個監聽服務端的線程 Thread threadServer = null; private void btn_Click(object sender, EventArgs e) { clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); if (string.IsNullOrEmpty(ipAddress.Text.ToString())) { MessageBox.Show("監聽ip地址不能為空!"); return; } if (string.IsNullOrEmpty(port.Text.ToString())) { MessageBox.Show("監聽端口不能為空!"); return; } IPAddress ip = IPAddress.Parse(ipAddress.Text.Trim()); IPEndPoint endpoint = new IPEndPoint(ip, int.Parse(port.Text.Trim())); try { //這里客戶端套接字連接到網絡節點(服務端)用的方法是Connect 而不是Bind clientSocket.Connect(endpoint); } catch { chatContent.AppendText("連接失敗!"); } // 創建一個線程監聽服務端發來的消息 threadServer = new Thread(recMsg); threadServer.IsBackground = true; threadServer.Start(); } /// <summary> /// 接收服務端發來的消息 /// </summary> private void recMsg() { while (true) //持續監聽服務端發來的消息 { //定義一個1M的內存緩沖區 用於臨時性存儲接收到的信息 byte[] arrRecMsg = new byte[1024 * 1024]; int length = 0; try { //將客戶端套接字接收到的數據存入內存緩沖區, 並獲取其長度 length = clientSocket.Receive(arrRecMsg); } catch { return; } //將套接字獲取到的字節數組轉換為人可以看懂的字符串 string strRecMsg = Encoding.UTF8.GetString(arrRecMsg, 0, length); //將發送的信息追加到聊天內容文本框中 chatContent.AppendText("服務端(" + GetCurrentTime() + "):" + strRecMsg + "\r\n"); } } /// <summary> /// 發送消息到服務端 /// </summary> /// <param name="msg"></param> private void clientSendMsg(string msg) { byte[] sendMsg = Encoding.UTF8.GetBytes(msg); clientSocket.Send(sendMsg); chatContent.AppendText("客戶端(" + GetCurrentTime() + "):" + msg + "\r\n"); } /// <summary> /// 獲取當前系統時間的方法 /// </summary> /// <returns>當前時間</returns> private DateTime GetCurrentTime() { DateTime currentTime = new DateTime(); currentTime = DateTime.Now; return currentTime; }
GitHub源碼地址:https://github.com/51042309/Socket