如何用C#做一個簡單的UDP協議聊天軟件

一款基於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

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);
      
  • 指定發送地址和端口號
    //獲取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
      
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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章