欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

UDP实现一个简易的聊天室 (Unity&&C#完成)

程序员文章站 2022-08-10 10:53:37
效果展示(尚未完善) using System.Collections; using System.Collections.Generic; using UnityEngine; using System.Threading; using System.Net; using System.Net.S ......

  效果展示(尚未完善)

UDP实现一个简易的聊天室 (Unity&&C#完成)

UDP实现一个简易的聊天室 (Unity&&C#完成)chatudpclienttest
UDP实现一个简易的聊天室 (Unity&&C#完成)
using system.collections;
using system.collections.generic;
using unityengine;
using system.threading;
using system.net;
using system.net.sockets;
using system.text;
using common;
using uiwidgetssamples;
using system;

/// <summary>
/// 服务端
/// </summary>
public class chatudpservertest : monobehaviour
{
    public string serverip;
    //ip地址
    public int serverport;
    //端口
    //1.创建scoket对象 ip port
    private thread thread;
    private udpclient udpseivic;
    public void start()
    {
        chatview = transform.findchildbyname("chatview").
            getcomponent<chatview>();
        //给端口和ip
        //构建终结点  ip和一个端口
        ipendpoint localep = new 
            ipendpoint(ipaddress.parse(serverip), serverport);
        udpseivic = new udpclient(localep);

        thread = new thread(receivemessage);
        thread.start();
    }
    
    /// <summary>
    /// 接收消息
    /// </summary>
    private void receivemessage()
    {
        while (true)
        {
            ipendpoint remote = new
                ipendpoint(ipaddress.any, 0);
            //创建任意终结点
            //ref
            byte[] date = udpseivic.receive(ref remote);
            //receive接收消息  如果没有收到消息 线程阻塞  放在线程中
            string msg = encoding.utf8.getstring(date);
            //获取的客户都安信息
            debug.log(remote.address + "===" + remote.port);
            //如果接收客户端的消息,会把任意终结点修改为客户端的终结点
            threadcrosshelper.instance.executeonmainthread(() => { showmessage(msg); });
        }
    }
    private chatview chatview;
    /// <summary>
    /// 显示消息
    /// </summary>
    /// <param name="msg"></param>
    public void showmessage(string msg)
    {
        chatview.datasource.add(new chatline()
        {
            username = "annns",
            message = msg,
            time = datetime.now,
            type = chatlinetype.user,
        });
    }
    private void onapplicationquit()
    {
        udpseivic.close();
        thread.abort();
    }
}
chatudpservertest

脚本引用的工具箱

  1. monosingleton (泛型单例)
  2. threadcrosshelper (为子线程提供,可以在主线程中执行的方法)
  3. transformhelper(根据名称查找后代元素)
UDP实现一个简易的聊天室 (Unity&&C#完成)
using system.collections;
using system.collections.generic;
using unityengine;

namespace common
{
    /// <summary>
    /// 
    /// </summary>
    public class monosingleton<t> : monobehaviour where t : monosingleton<t>
    {
        //public static t instance
        //{
        //    get;
        //    private set;
        //}
        //private void awake()
        //{
        //    instance = this as t;
        //} 
        //按需加载
        private static t instance;
        public static t instance
        {
            get
            {
                if (instance == null)
                {
                    //在场景中查找对象
                    instance = findobjectoftype<t>();
                    if (instance == null)
                    {
                        //创建游戏对象 附加 脚本对象
                        new gameobject("singleton of " + typeof(t)).addcomponent<t>();//立即执行awake
                    }
                    else
                    {
                        instance.initialized();
                    }
                }
                return instance;
            }
        }

        protected virtual void initialized()
        {

        }

        [tooltip("是否需要跨场景不销毁")]
        public bool isdontdestroy = true;

        //如果管理类自行附加到物体中
        //在awake中为instance赋值 
        protected void awake()
        {
            if (isdontdestroy)
            {
                dontdestroyonload(gameobject);
            }
            if (instance == null)
            {
                instance = this as t;
                instance.initialized();
            }
        }
    }
}
monosingleton
UDP实现一个简易的聊天室 (Unity&&C#完成)
using system;
using system.collections;
using system.collections.generic;
using unityengine;
 
namespace common
{
    /// <summary>
    /// 
    /// </summary>
    public class threadcrosshelper : monosingleton<threadcrosshelper>
    {
        /// <summary>
        /// 延迟项
        /// </summary> 
        class delayeditem
        {
            public action currentaction { get; set; }
            public datetime time { get; set; }
        }

        private list<delayeditem> actionlist;
        //private list<action> actionlist;
        //private list<float> timelist;

        protected override void initialized()
        {
            base.initialized();

            actionlist = new list<delayeditem>(); 
        }

        private void update()
        { 
            for (int i = actionlist.count - 1; i >= 0; i--)
            {
                //到时间
                if (actionlist[i].time <= datetime.now)
                {
                    lock (actionlist)
                    {
                        actionlist[i].currentaction();//执行
                        actionlist.removeat(i);//从列表中移除 
                    }
                }
            }
        }
        /// <summary>
        /// 为子线程提供,可以在主线程中执行的方法
        /// </summary>
        /// <param name="action"></param>
        /// <param name="dealy"></param>
        public void executeonmainthread(action action, float dealy = 0)
        {
            delayeditem item = new delayeditem()
            {
                currentaction = action,
                //time = time.time + dealy
                time = datetime.now.addseconds(dealy)
            };
            lock (actionlist)
            {
                actionlist.add(item);
            }
        }
    }
}
threadcrosshelper
UDP实现一个简易的聊天室 (Unity&&C#完成)
using system.collections;
using system.collections.generic;
using unityengine;

namespace common
{
    /// <summary>
    /// 变换组件助手类
    /// </summary>
    public static  class transformhelper
    { 
        /// <summary>
        /// 未知层级,根据名称查找后代元素
        /// </summary>
        /// <param name="currenttf"></param>
        /// <param name="childname"></param>
        /// <returns></returns>
        public static transform findchildbyname(this transform currenttf, string childname)
        {
            transform childtf = currenttf.find(childname);
            if (childtf != null) return childtf;
            //将问题推迟给子物体
            for (int i = 0; i < currenttf.childcount; i++)
            {
                //在方法体内部,又遇到了相同的问题,所以需要调用自身。
                childtf = findchildbyname(currenttf.getchild(i), childname);
                if (childtf != null) return childtf;
            }
            return null;
        }
    }
}
transformhelper