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()
    //{

    //}
}

 

posted @ 2019-12-26 10:45  低调的风仔  阅读(4339)  评论(0编辑  收藏  举报