一款基於Udp協議的聊天軟件 by C# WinForm
Information:
最近在學計算機網絡,學到了TCP協議和UDP協議,這裏具體就不說這兩個協議了,主要講講如何通過C#Winform來寫一個聊天程序,用實踐來加深理論。由於學習時間的安排,我分階段實現這個程序的功能。TCP和UDP的實現都差不多,都是用的套接字,所以我就只介紹UDP的了
MyTask:
- OneChat task
- Simple UI
- Winform窗體搭建
- 實現UDP通信
- UDP Send data
- UDP Receive data
- Simple UI
Let’s Start The Project On VS2019
——————————————————————————————————————————————————
1. 創建OneChat工程
2. 設計WinForm窗體,添加所需控件
3. 更改控件屬性
4. 實現UDP發送
- 引用所需要的類
using System.Net.Sockets; using System.Net; using System.Threading; //用於進行多線程編程,接收消息需要用到
- 創建一個Socket對象
/* 實列化Socket套接字對象 * 實列化參數: * AddressFamily(地址族) :InterNetwork ——> IP 版本 4 的地址 * SocketType(套接字類型):Dgram ——> UDP對應數據報,而TCP對應的是Stream * ProtocolType(支持類型):UDP ——> UDP協議 * */ Socket sSndMag = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
- 創建一個Socket對象
- 指定發送地址和端口號
//獲取UI中對方的IP地址 IPAddress ipaddrRemote = IPAddress.Parse(this.tB_RemoteIp.Text); //創建IPEndPoint並實列化——>指定地址和端口號 EndPoint edpRemote = new IPEndPoint(ipaddrRemote, Convert.ToInt16(this.tB_RemotePort.Text));
- UDP發送數據
//UDP發送數據,發送前需要把發送的內容轉成字節類型的 sSndMag.SendTo(System.Text.Encoding.Default.GetBytes(this.rtB_SendMsg.Text), edpRemote);
- 關閉套接字
//關閉套接字 sSndMag.Close();
5. 實現UDP接收
-
全局變量
Thread t; string RecvData; static Socket UdpClient; //string led;
-
接收函數
- 創建並是實列化IPEndPoint
- 指定IP Address爲Any和Port = 0
- Create a Buffer用於接收數據
- 用ReceiveFrom方法接收
- 顯示地址、端口和數據(Bytes -> String)
void ReciveMsg() { while (true) { EndPoint point = new IPEndPoint(IPAddress.Any, 0);//用來保存發送方的ip和端口號 byte[] buffer = new byte[1024]; int length = UdpClient.ReceiveFrom(buffer, ref point);//接收數據報 //led = Encoding.Default.GetString(buffer, 0, length); RecvData += "【from "+ point+"】:" + Encoding.Default.GetString(buffer, 0, length);//Encoding.UTF8.GetString方法不能支持中文 RecvData += "\r\n";//接收完換行 /*********************************************************************/ //非主線程訪問,會報錯 CheckForIllegalCrossThreadCalls =false 去掉檢查 //led_ctrl();//這裏我用來調試Esp8266開發板的LED的,可屏蔽 this.rtB_RecvMsg.Text = RecvData; /*********************************************************************/ } }
-
創建線程
- 在MainForm_Load中創建一個Client套接字對象並是實列化
- 在MainForm_Load中創建線程,在線程中調用接收函數,然後打開線程
private void MainForm_Load(object sender, EventArgs e) { CheckForIllegalCrossThreadCalls = false;//屏蔽掉線程報錯,這裏不是最好的辦法,我代碼裏面用的另外一種方法 this.tB_LocalIp.Text = GetLocalIp(); //獲取本機地址 this.tB_RemoteIp.Text = this.tB_LocalIp.Text; //方便調試,可屏蔽 UdpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPEndPoint localIPEndPoint = new IPEndPoint(IPAddress.Parse(this.tB_LocalIp.Text),Convert.ToInt16(this.tB_LocalPort.Text)); UdpClient.Bind(localIPEndPoint); //開啓線程 t = new Thread(ReciveMsg); t.Start(); }
-
Note:
- 接收函數非主線程,而textBox是在主進程中創建的,所以接收函數不能調用主線程創建的控件,否則會報錯,我用了一個最簡單但不是最好的方法
//去掉檢查 CheckForIllegalCrossThreadCalls =false
- 接收函數非主線程,而textBox是在主進程中創建的,所以接收函數不能調用主線程創建的控件,否則會報錯,我用了一個最簡單但不是最好的方法
6. 實現清除文本框數據功能
- 清除發送數據文本框內容
private void btn_ClrSendMsg_Click(object sender, EventArgs e) { rtB_SendMsg.Text = ""; }
- 清除接收數據文本框內容
private void btn_ClrRecvMsg_Click(object sender, EventArgs e) { RecvData = ""; this.rtB_RecvMsg.Text = ""; }
效果圖:
————————————————————————————
代碼下載鏈接: OneChat