C# Socket之UDP通信


  Socket之間的通信可以類比生活中打電話的案例。任何用戶在通話之前,首先要占有一部電話機,相當於申請一個Socket,同時要知道對方的號碼,相當於對方有一個固定的Socket,然后向對方撥號呼叫,相當於發出連接請求。假如對方在場並空閑,拿起 電話話筒,雙方就可以進行通話了。雙方的通話過程,是一方向電話機發出信號和對方從電話機接收信號的過程,相當於向socket發送數據和從socket接收數據。通話結束后,一方掛起電話機,相當於關閉socket,撤銷連接。 注意:Socket不僅可以在兩台電腦之間通信,還可以在同一台電腦上的兩個程序間通信,例如TUIO就是利用UDP通信的。

  Socket主要有兩種類型:

  1. 流式Socket

          是一種面向連接的Socket,針對於面向連接的TCP服務應用,安全,但是效率低

     2,數據報式Socket

          是一種無連接的Socket,對應於無連接的UDP服務應用,不安全,但效率高

  我們這里主要是講一下UDP通信,TCP通信的話首先需要開啟服務端通信,然后客戶端才可以去連接,服務端與客戶端代碼是不一樣的,連接后是不會斷開的,所以不會出現數據丟失的情況,但效率很低。UDP的話是非連接的,所以不存在服務端和客戶端的區別。各主機之間都是平級的,發送信息的話,UDP建立socket通信后只需要知道對方的IP與端口,直接發送信息就好,它不管信息是否對方是否收到,我只管發,所以可能會出現對方不在線或者其他原因沒有接受到信息的情況,UDP接受消息是只要是發給我的我就統統接受,所以UDP的收發消息大概是這么個情況,因為UDP的靈活,高效性,所以多用於中控程序。

    socket通信端口號范圍:0-65535,總共能表示65536個數。

   按端口號可分為3大類

  (1)公認端口(WellKnownPorts):從0到1023,它們緊密綁定(binding)於一些服務。通常這些端口的通訊明確表明了某種服務的協議。例如:80端口實際上總是HTTP通訊。

  (2)注冊端口(RegisteredPorts):從1024到49151。它們松散地綁定於一些服務。也就是說有許多服務綁定於這些端口,這些端口同樣用於許多其它目的。例如:許多系統處理動態端口從1024左右開始。

  (3)動態和/或私有端口(Dynamicand/orPrivatePorts):從49152到65535。理論上,不應為服務分配這些端口。實際上,機器通常從1024起分配動態端口。

   我們利用UDP通信的時候綁定端口,取1024到49151就好,接下來上代碼,這是一個單例腳本,無需掛載,程序開始時調用一下ConnectStart方法開啟通信就好,記得關閉程序時要調用一下Close1方法來關閉開啟的線程,否則調試的時候線程一直開啟着,可能會出現程序卡死的情況。

***********************************
*    Description:udp通信
*    Mountpoint:單例無需掛載
*    Date:2019
*    Version:版本
*    Author:LJF
***********************************/
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;
using LjfLog;

public class UDPclient{

    static UDPclient instance;
    public static UDPclient Instance
    {
        get
        {
            if (instance == null)
                instance = new UDPclient();
            return instance;
        }
    }
   
    Socket sock;
    //本機ip、端口
    IPEndPoint ip;
    //用來接收消息的any
    EndPoint ipany;

    //接收方的IP端口
    IPEndPoint ie;

    Thread ReceiveListern;
    //Dictionary<string, NetObject> netObjectDic = new Dictionary<string, NetObject>();//網絡對象字典
    public void ConnectStart(int port)
    {
        Debuger.EnableSave = true;
        sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        //sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);//開啟群發功能
        //ie = new IPEndPoint(IPAddress.Broadcast,5555);//廣播端口
        ip = new IPEndPoint(IPAddress.Parse(GetHostIpAddress()), port);      
        sock.Bind(ip);
        Debug.Log("服務器啟動了");
        //
        IPEndPoint end = new IPEndPoint(IPAddress.Any, 0);
        ipany = (EndPoint)end;

        ReceiveListern = new Thread(Receive);
        ReceiveListern.Start();


    }
    public string str;
    public bool isaccept;
    //收消息
    public void Receive()
    {
        while (true)
        {
            byte[] byt = new byte[1024];
            int length = sock.ReceiveFrom(byt, ref ipany);
            if (length > 0)
            {
                isaccept = true;
                str = Encoding.UTF8.GetString(byt, 0, length);
                Debuger.Log(string.Format("收到主機:{0}發來的消息|{1}", ipany, str));
            }
        }
    }
    //發消息 單發
    public void SendMessage(string msg)
    {
        byte[] byt = new byte[1024];//1K
        byt = Encoding.UTF8.GetBytes(msg);
        //sock.SendTo(byt, byt.Length, SocketFlags.None,ie);//ie為接收方的iP端口
    }

    //動態獲取自身ip
    private string GetHostIpAddress()
    {
        string name = Dns.GetHostName();
        IPAddress[] ipadrlist = Dns.GetHostAddresses(name);
        foreach (IPAddress ipa in ipadrlist)
        {
            if (ipa.AddressFamily == AddressFamily.InterNetwork)
                return ipa.ToString();
        }
        return "";
    }

    //釋放線程、Sock資源
    public void Close1()
    {
        if (ReceiveListern != null)
        {
            ReceiveListern.Abort();
        }
        if (sock != null)
        {
            sock.Close();
        }
        Debuger.Dispose();
    }

    //void OnApplicationQuit()
    //{
       
    //}
    //void OnDestory()
    //{

    //}
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM