Socket.IO for Unity 简要介绍和简单应用

原创 2015年11月19日 11:31:15

在项目中使用到了Socket.IO for unity这个Asset Store上免费的库,这里将简要的介绍一下它的结构,已经使用中的注意事项。

目录结构

这里写图片描述
上面为包的目录结构,简单的介绍一下具体的内容:

  • JSONObject - 打包与解析JSON格式
  • Prefabs - 简单的SocketIO客户端的Prefab,实际上其就是一个attach了SocketIOComponent的Unity GameObject
  • Scences - Unity3d的测试Scene,用于简单测试
  • Scripts - Unity3d的MonoBehavior 脚本和其使用到的类, 其实只有一个SocketIOComponent是脚本,其他都是该脚本使用到的帮助类
  • Server - 目录下的存放的是NodeJs服务器端的测试Js脚本,对于于客户端的测试用例,在实际的开发中可以删除。
  • WebSocketSharp- 目录下存放的是C#的WebSocket的实现,不依赖于任何Unity3d的代码。
  • readme.txt - 简单的帮助文档,说明如何使用该package。

核心类解析

  • SocketIOComponent
    SocketIOComponent这个脚本是我们使用该Socket.IO for Unity package最重要的一个类,其集成了报文的封装,解析,回掉函数,Ping,Pong控制帧,以及WebSocket的数据传输。 基本的结构图如下:
    这里写图片描述

如下说明

  1. SocketIOComponent至少使用了两个独立的线程用于WebSocket数据以及控制的传输,至于为什么使用PingThread (Ping和Pong),这个是WebSocket协议控制的需求,详情请https://tools.ietf.org/html/rfc6455#section-5.5
  2. Connect函数用于连接WebScoket 的服务器, Emit函数用于发送数据到服务器,On函数用于注册回掉函数用于处理来自服务器的报文。
  3. Unity3d的Update线程用于服务器发送而来的报文发送,包含ACK报文(客户端传送给服务器的确认回掉)和Event报文(服务器传送给客户端的报文),对于ACK报文,通常是客户端需要同步的获取服务器的消息的时候使用,在该情况下容易产生死锁问题。 解决的办法是新增加一个单独的线程来处理ACK报文和Event消息。(后面会详细介绍如何实现)
  4. SocketIOEvent和JSONObject用于SocketIOComponent的用户的报文的发送与接收。SocketIOEvent如下
        // 事件的名称
        public string name { get; set; }
        // 具体的数据内容
        public JSONObject data { get; set; }
        public SocketIOEvent(string name) : this(name, null) { }
        public SocketIOEvent(string name, JSONObject data)
        {
            this.name = name;
            this.data = data;
        }

        public override string ToString()
        {
            return string.Format("[SocketIOEvent: name={0}, data= {1}]", name, data);
        }
    }
}

如何封装同步函数

SocketIOComponent提供了很简介的方法给我们向服务器发送消息(SocketIOComponent::Emit函数)和服务器接收消息(SocketIOComponent::On函数)。但是其无法让我们从服务器同步的获取消息。 比如说,我们需要从服务器同步的获取数据,当前的实现是无法做到的。修改方法如下:

  1. 客户端
    将SocketIOComponent的Update函数的处理移动到一个新增加的线程中,不依赖于Unity3d的线程。如下:
    public void Connect()
    {
    connected = true;

        socketThread = new Thread(RunSocketThread);
        socketThread.Start(ws);
    
        pingThread = new Thread(RunPingThread);
        pingThread.Start(ws);
    
         *// 新增加callback线程
        callbackThread = new Thread(RunCallbackThread);
        callbackThread.Start(ws);*
    }
    

    private void RunCallbackThread(object obj)
    {
    while(connected)
    {
    // check the msg queue count with the time.
    msgSemaphore.WaitOne(600);
    if (eventQueue.Count > 0 || ackQueue.Count > 0 || wsConnected != ws.IsConnected)
    {
    lock (eventQueueLock)
    {
    while (eventQueue.Count > 0)
    {
    EmitEvent(eventQueue.Dequeue());
    }
    }

                lock (ackQueueLock)
                {
                    while (ackQueue.Count > 0)
                    {
                        InvokeAck(ackQueue.Dequeue());
                    }
                }
    
                if (wsConnected != ws.IsConnected)
                {
                    wsConnected = ws.IsConnected;
                    if (wsConnected)
                    {
                        EmitEvent("connect");
                    }
                    else
                    {
                        EmitEvent("disconnect");
                    }
                }
            }
    
            // GC expired acks
            if(ackList.Count == 0) { continue; }
            if(DateTime.Now.Subtract(ackList[0].time).TotalSeconds < ackExpirationTime) { continue; }
            ackList.RemoveAt(0);  
        }
    

    // 同步的从服务器端获取数据
    private void GetDataFromServerBySync()
    {
    webSocketWaitEvent.Reset();
    SocketIoComponent.Emit(‘testSync’, (JSONObject jsonData) => {
    // The lib always use the to wrapper the json data.
    hallManagerData = HallJson.ToHallManagerData(jsonData [0]);
    webSocketWaitEvent.Set();
    });
    webSocketWaitEvent.WaitOne(500);
    return;
    }

  2. 服务器端
    io.sockets.on(‘connection’, function(socket){
    console.log(‘connection is called!’);
    console.log(socket.id)

    socket.on( ‘testSync’, function(callback){
    // 回调函数
    callback(testJson);
    });
    });

3 做此修改后请注意,回调函数将不在Unity3d的主线程中处理,所以还需要做一点的封装,将最后的事件放入Update线程中处理。 如果没有同步从Server端获取数据的需求,就不要做上述的修改了。

经过初步测试,从服务器端获取超过10k的数据,大约需要4ms左右。服务器为NodeJs,在本地通过127.0.0.1的端口传送。

使用Node.js+socket.io制作服务端,unity+socket.io for unity 制作客户端 ,验证位置同步Demo

使用Node.js+socket.io制作服务端,unity+socket.io for unity 制作客户端 ,验证位置同步Demo (Javascript代码可使用Webstorm等IDE进行编...
  • zhangzhaoyuxunlei
  • zhangzhaoyuxunlei
  • 2016年11月16日 09:49
  • 576

Unity3d 下websocket的使用

今天介绍一下如何在Unity3d下使用WebSocket。 首先介绍一下websocket,socket,和http的区别与联系,然后介绍一下websocket的一些开源的项目。 WebSocke...
  • leoleocs
  • leoleocs
  • 2015年09月30日 11:41
  • 10870

Socket.IO for Unity 简要介绍和简单应用

在项目中使用到了Socket.IO for unity这个Asset Store上免费的库,这里将简要的介绍一下它的结构,已经使用中的注意事项。目录结构 上面为包的目录结构,简单的介绍一下具体的内容...
  • leoleocs
  • leoleocs
  • 2015年11月19日 11:31
  • 9721

WebSocket与Socket.io

认识HTML5的WebSocket 在HTML5规范中,我最喜欢的Web技术就是正迅速变得流行的WebSocket API。WebSocket提供了一个受欢迎的技术,以替代我们过去几年一直在用的...
  • aaa333qwe
  • aaa333qwe
  • 2017年12月11日 13:55
  • 82

unity3D中使用Socket进行数据通信(三)

今天跟大家继续学习下socket,由于最近有个招标参数需要给之前的一款产品做教师端以及后台数据库部分,忙了将近两个礼拜,今天刚发布了,就继续我们的socket通信部分。          之前服务端一...
  • lj34207310
  • lj34207310
  • 2016年03月11日 18:23
  • 10852

socket.io client api

有些文章在国外的经常访问不进去,复制下来以便访问和查找
  • niusibao
  • niusibao
  • 2015年12月16日 14:51
  • 444

socket.io框架学习

socket.io框架是用于网页中实时通信,一般用于开发聊天室等实时性较强的系统模块 一开始从官网http://socket.io/上down了一个demo下来,这个demo里面只有基本的收发消息的...
  • u013444046
  • u013444046
  • 2016年05月26日 17:24
  • 1190

Socket.io show client socket ID

http://stackoverflow.com/questions/7702461/socket-io-custom-client-id
  • SalmonellaVaccine
  • SalmonellaVaccine
  • 2014年08月06日 07:12
  • 986

如何解决WebSocket-Sharp在Unity3d中无法跨与访问不同网断服务器

我们需要使用 Socket Policy Server. Unity3D 包含了一个简单的 Socket Policy Server (sockpol.exe). 你需要在启动你的应用之前启动它 ...
  • molti
  • molti
  • 2014年12月24日 14:26
  • 3001

socket.io实践篇(1)

http://blog.csdn.net/jiangcs520/article/details/17287531 2013-12-13 17:27 1951人阅读 评论(1) 收藏 举报 ...
  • oMingZi12345678
  • oMingZi12345678
  • 2014年11月21日 11:11
  • 1274
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Socket.IO for Unity 简要介绍和简单应用
举报原因:
原因补充:

(最多只允许输入30个字)