网络通信框架(C# Unity)(异步)

前言

上一章写了Socket相关的概念并且通过同步方法实现了Socket编程,但是由于同步方法是阻塞的,如果我们在Unity的主线程中使用,在阻塞期间会导致游戏进程直接卡死。
为了让游戏流畅运行同时让服务端异步处理多个客户端请求,我们通常会采用异步的方法进行Socket编程。

同步和异步

同步(Synchronous)和异步(Asynchronous)是指代码执行的方式和模式。
一般来说,同步操作是按顺序执行的,每个操作会阻塞当前线程,直到操作完成才会继续执行后续代码,在同步操作中,调用方会等待被调用方法的返回结果,然后才能继续执行后续代码。而异步操作允许在操作进行的同时执行其他代码,而不会阻塞当前线程,不需要等待操作完成,就可以继续执行后续代码
相对而言,异步操作能提高应用程序的响应性和并发性,允许更好地利用系统资源,同时也能避免阻塞关键线程。

网络管理类 (异步)

较上一篇文章 只需要更改网络管理类即可 下面是代码示例

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace vs_Day03_practice
{
    internal class NetMgr2:Singleton<NetMgr2>
    {
        Socket socket;
        public List<Client> sockets = new List<Client>(); //所有玩家集合
        public void Init()
        {
            socket=new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint ip=new IPEndPoint(IPAddress.Any, 9999);
            socket.Bind(ip);
            socket.Listen(10);
            socket.BeginAccept(OnAccept, null);
        }
        private void OnAccept(IAsyncResult ar)
        {
            Socket client=socket.EndAccept(ar);
            IPEndPoint ip=client.RemoteEndPoint as IPEndPoint;
            Console.WriteLine(ip.Address+":"+ip.Port);
            Client cli=new Client();
            cli.socket=client;
            //玩家连接成功 放入集合
            sockets.Add(cli);
            cli.socket.BeginReceive(cli.data, 0, cli.data.Length,SocketFlags.None,OnReceive,cli);
            socket.BeginAccept(OnAccept, null);
        }
        private void OnReceive(IAsyncResult ar)
        {
            //取出参数
            Client cli=ar.AsyncState as Client;
            //获取消息长度
            int len=cli.socket.EndReceive(ar);
            if (len <= 0)
            {
                cli.socket.Shutdown(SocketShutdown.Both);
                cli.socket.Close();
                sockets.Remove(cli); //删除
                告诉所有人该玩家下线了
                //if (cli.nick != null && cli.nick != "")
                //{
                //    foreach (var item in sockets)
                //    {
                //        if (item.nick != null &&  item.nick != "")
                //        {
                //            Send(item.socket, MsgID.S2C_Leave, UTF8Encoding.UTF8.GetBytes(cli.nick));
                //        }
                //    }
                //}
                return;
            }
            //截取消息
            //data=head+body
            byte[] data=cli.data.Take(len).ToArray();
            //取出id
            //head是int转成byte数组,固定是4位
            //ToInt32只取4位
            int id=BitConverter.ToInt32(data, 0);
            //body的长度=len-4
            byte[] body=data.Skip(4).ToArray();
            //同步传socket异步传Client
            MessageCenter.Ins.Broadcast(id, body,cli);
            cli.socket.BeginReceive(cli.data, 0, cli.data.Length, SocketFlags.None, OnReceive, cli);
        }
        public void Send(Socket client,int id, byte[] body)
        {
            byte[] head=BitConverter.GetBytes(id);
            //拼接数组
            byte[] data=head.Concat(body).ToArray();
            client.BeginSend(data, 0, data.Length, SocketFlags.None, OnSend, client);
        }
        private void OnSend(IAsyncResult ar)
        {
            Socket client=ar.AsyncState as Socket;
            int len = client.EndSend(ar);
            Console.WriteLine("发送成功,发送长度"+len);
        }
    }
}
internal class Client //用到的自定义类
{
    public Socket socket;
    public byte[] data=new byte[1024];
    public string nick;//昵称 登录时注册的名字
}

  • 12
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我不食卷心菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值