[Unity Socket]在Unity中如何实现异步Socket通信技术

在刚刚开发Unity项目的过程中,需要用到即时通信功能来完成服务器与客户端自定义的数据结构封装。

现在将部分主要功能的实现代码抽取出来实现了可以异步Socket请求的技术Demo。

客户端脚本ClientScript

/// <summary>
/// Client Script.
/// Created By 蓝鸥3G 2014.08.23
/// </summary>

using UnityEngine;
using System.Collections;

public class ClientScript: MonoBehaviour {
    string msg = "";
    // Use this for initialization

    LOSocket client;
    void Start () {
        client = LOSocket.GetSocket(LOSocket.LOSocketType.CLIENT);
        client.InitClient ("127.0.0.1", 2222, ((string content) => {
            //收到服务器的回馈信息
        }));
    }

    void OnGUI() {
        msg = GUI.TextField(new Rect(0, 0, 500, 40), msg);
        if(GUI.Button(new Rect(0, 50, 100, 30), "Send"))
        {

            client.SendMessage (msg);
        }
    }
} 

服务器端脚本

/// <summary>
/// Server Script.
/// Created By 蓝鸥3G 2014.08.23
/// </summary>
///
///
using UnityEngine;
using System.Collections;

public class ServerScript : MonoBehaviour {

    private string receive_str;
    LOSocket server;
    // Use this for initialization
    void Start ()
    {
        server = LOSocket.GetSocket(LOSocket.LOSocketType.SERVER);
        //初始化服务器
        server.InitServer((string content) => {
            receive_str = content;
        });
    }

    void OnGUI()
    {
        if (receive_str != null)
        {
            GUILayout.Label (receive_str);
        }
    }
}

LOSocket框架

/// <summary>
/// LOSocket.
/// Created By 蓝鸥3G 2014.08.23
/// </summary>
///
///
using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Text;

//收到消息后的委托回调
public delegate void ReceiveCallBack(string content);

public class LOSocket{

    //可以创建的Socket端口类型
    public enum LOSocketType
    {
        CLIENT = 0,
        SERVER = 1,
    }
    #region --------取消构造器
    private LOSocket()
    {
    }

    #endregion

    #region --------公共代码
    //通过静态方法获取不同的端口类型
    public static LOSocket GetSocket(LOSocket.LOSocketType type)
    {
        LOSocket socket = null;

        switch (type) {
        case LOSocketType.CLIENT:
            {
                //创建一个新的客户端
                socket = new LOSocket ();
                break;
            }
        case LOSocketType.SERVER:
            {
                //获取服务端
                socket = GetServer ();
                break;
            }
        }

        return socket;
    }

    #endregion
    #region --------客户端部分代码
    private Socket clientSocket;

    //声明客户端收到服务端返回消息后的回调委托函数
    private ReceiveCallBack clientReceiveCallBack;
    //用来存储服务端返回的消息数据
    byte[] Buffer = new byte[1024];

    //初始化客户端Socket信息
    public void InitClient(string ip,int port,ReceiveCallBack ccb)
    {
        this.clientReceiveCallBack = ccb;
        this.clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        IPAddress address = IPAddress.Parse (ip);
        IPEndPoint ep = new IPEndPoint (address, port);

        this.clientSocket.Connect(ep);
        //开始异步等待接收服务端消息
        this.clientSocket.BeginReceive (Buffer, 0, Buffer.Length, SocketFlags.None, new System.AsyncCallback(ReceiveFromServer), this.clientSocket);
    }

    //收到服务端返回消息后的回调函数
    void ReceiveFromServer(System.IAsyncResult ar)
    {
        //获取当前正在工作的Socket对象
        Socket worker = ar.AsyncState as Socket;
        int ByteRead=0;
        try
        {
            //接收完毕消息后的字节数
            ByteRead = worker.EndReceive(ar);
        }
        catch (System.Exception ex)
        {
            this.clientReceiveCallBack (ex.ToString ());
        }
        if (ByteRead > 0)
        {
            string Content = Encoding.Default.GetString (Buffer);
            //通过回调函数将消息返回给调用者
            this.clientReceiveCallBack (Content);
        }
        //继续异步等待接受服务器的返回消息
        worker.BeginReceive(Buffer, 0, Buffer.Length, SocketFlags.None, new System.AsyncCallback(ReceiveFromServer), worker);
    }

    //客户端主动发送消息
    public void SendMessage(string message)
    {
        if (message == null)
            return;

        message += "\r\n";
        byte[] sendData = Encoding.UTF8.GetBytes (message);

        //异步发送消息请求
        clientSocket.BeginSend (sendData, 0, sendData.Length, SocketFlags.None, new System.AsyncCallback (SendToServer), clientSocket);
    }
    //发送消息结束的回调函数
    void SendToServer(System.IAsyncResult ar)
    {
        Socket worker = ar.AsyncState as Socket;
        worker.EndSend (ar);
    }

    #endregion

    #region -------服务器部分代码
    //服务器端收到消息的存储空间
    byte[] ReceiveBuffer = new byte[1024];
    //服务器收到消息后的回调委托
    private ReceiveCallBack callback;

    //单例模式
    private static LOSocket serverSocket;
    private static LOSocket GetServer() {
        if (serverSocket == null) {
            serverSocket = new LOSocket();
        }
        return serverSocket;
    }  

    //初始化服务器信息
    public void InitServer(ReceiveCallBack cb) {
        this.callback = cb;
        // 1.
        Socket server_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        // 2.
        IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 2222);
        // 3.
        server_socket.Bind(endPoint);
        // 4.
        server_socket.Listen(10);
        // 5.开始异步等待客户端的请求链接
        server_socket.BeginAccept (new System.AsyncCallback (Accept), server_socket);

        this.callback ("开启服务器" + endPoint.ToString());
    }

    //接受到客户端的链接请求后的回调函数
    void Accept(System.IAsyncResult ar){
        //获取正在工作的Socket对象
        Socket socket = ar.AsyncState as Socket;
        //存储异步操作的信息,以及用户自定义的数据
        Socket worker = socket.EndAccept(ar);  

        SocketError error;

        //开始异步接收客户端发送消息内容
        worker.BeginReceive (ReceiveBuffer, 0, ReceiveBuffer.Length, SocketFlags.None, new System.AsyncCallback (Receive), worker);
        //继续异步等待新的客户端链接请求
        socket.BeginAccept(new System.AsyncCallback(Accept), socket);  

    }
    //服务端收到客户端的消息后的回调函数
    void Receive(System.IAsyncResult ar)
    {
        //获取正在工作的Socket对象
        Socket worker = ar.AsyncState as Socket;
        int ByteRead=0;
        try
        {
            ByteRead = worker.EndReceive(ar);
        }
        catch (System.Exception ex)
        {
            this.callback (ex.ToString ());
        }
        if (ByteRead > 0)
        {
            string Content = Encoding.Default.GetString (ReceiveBuffer);
            this.callback (Content);
        }
        //继续异步等待客户端的发送消息请求
        worker.BeginReceive(ReceiveBuffer, 0, ReceiveBuffer.Length, SocketFlags.None, new System.AsyncCallback(Receive), worker);
    }
    #endregion
}
时间: 2024-10-05 23:36:07

[Unity Socket]在Unity中如何实现异步Socket通信技术的相关文章

Unity3D中简单的C#异步Socket实现

Unity3D中简单的C#异步Socket实现 简单的异步Socket实现..net框架自身提供了很完善的Socket底层.笔者在做Unity3D小东西的时候需要使用到Socket网络通信.于是决定自己研究研究. 经过不懈努力..O(∩_∩)O哈哈~..自我夸奖一下.终于搞定了.SimpleSocket.cs 由于笔者本身并不是专业的C#程序员.O(∩_∩)O哈哈~.大神就可以直接忽视这篇文章了.顾名思义.哈哈简单的Socket.给那些没接触的盆友参考借鉴下吧.服务社会了 注释一: 本例在编码上

python异步socket编程之二

三.异步client与异步server的通信 1. 服务端代码 pythone socket的server段,开放三个端口:10000,10001,10002. 例子中是每个server绑定一个端口,测试的时候需要分别开3个shell,分别运行. 这太麻烦了,就分别用三个Thread来运行这些services #!/usr/bin/env python # # -*- coding:utf-8 -*- # File: multithrd_socket_server.py # import opt

C# Unity游戏开发——Excel中的数据是如何到游戏中的 (二)

本帖是延续的:C# Unity游戏开发——Excel中的数据是如何到游戏中的 (一) 上个帖子主要是讲了如何读取Excel,本帖主要是讲述读取的Excel数据是如何序列化成二进制的,考虑到现在在手游中应用很广泛的序列化技术Google的ProtoBuf,所以本文也是按照ProtoBuf的方式来操作的.ProtoBuf是一个开源库,简单来说ProtoBuf就是一个能使序列化的数据变得更小的类库,当然这里指的更小是相对的.好了ProtBuf的东西就不在多说,以后会专门写一篇帖子的.本帖其实就相当于上

【Unity技巧】Unity中的优化技术

写在前面 这一篇是在Digital Tutors的一个系列教程的基础上总结扩展而得的~Digital Tutors是一个非常棒的教程网站,包含了多媒体领域很多方面的资料,非常酷!除此之外,还参考了Unity Cookie中的一个教程.还有很多其他参考在下面的链接中. 这篇文章旨在简要地说明一下常见的各种优化策略.不过对每个基础有非常深入地讲解,需要的童鞋可以自行去相关资料. 还有一些我认为非常好的参考文章: Performance Optimization for Mobile Devices

C# Unity游戏开发——Excel中的数据是如何到游戏中的 (三)

本帖是延续的:C# Unity游戏开发——Excel中的数据是如何到游戏中的 (二) 前几天有点事情所以没有继续更新,今天我们接着说.上个帖子中我们看到已经把Excel数据生成了.bin的文件,不过其实这样到游戏中还是不能用的.主要有两个方面,1.bin文件的后缀使我们随便取的名字,但是这种文件Unity不买账.因为Unity中的二进制文件必须是以.bytes命名的.2.在写文件之前其实还可以对二进制进行压缩,这样可以最大化节省设备空间.也就是说我们在生成数据实例后还需要做以下几件事:序列化 -

(转)【Unity技巧】Unity中的优化技术

写在前面 这一篇是在Digital Tutors的一个系列教程的基础上总结扩展而得的~Digital Tutors是一个非常棒的教程网站,包含了多媒体领域很多方面的资料,非常酷!除此之外,还参考了Unity Cookie中的一个教程.还有很多其他参考在下面的链接中. 这篇文章旨在简要地说明一下常见的各种优化策略.不过对每个基础有非常深入地讲解,需要的童鞋可以自行去相关资料. 还有一些我认为非常好的参考文章: Performance Optimization for Mobile Devices

【Unity编程】Unity中关于四元数的API详解

Unity中关于四元数的API详解 Quaternion类 Quaternion(四元数)用于计算Unity旋转.它们计算紧凑高效,不受万向节锁的困扰,并且可以很方便快速地进行球面插值. Unity内部使用四元数来表示所有的旋转. Quaternion是基于复数,并不容易直观地理解. 不过你几乎不需要访问或修改单个四元数参数(x,y,z,w); 大多数情况下,你只需要获取和使用现有的旋转(例如来自"Transform"),或者用四元数来构造新的旋转(例如,在两次旋转之间平滑插入). 大

python中asynchat异步socket命令/响应处理

该模块基于asyncore简化了异步客户端和服务器,并使其更容易元素处理由任意的字符串结束,或者是可变长度的的协议.它提供了抽象类async_chat,提供collect_incoming_data()和found_terminator()方法.循环和asyncore的一样,有2种信道:asyncore.dispatcher和asynchat.async_chat,可以自由混合信道.通常asyncore.dispatcher服务器通道在接收到连接请求时产生新的asynchat.async_cha

【Unity编程】Unity动画系统(一)

Unity动画系统 Unity动画系统,也称为"Mecanim",提供了以下功能: 简单的工作流程,设置动画的所有元素,包括对象,角色和属性. 支持导入外部创建的动画片段和使用内置动画编辑器制作的动画片段. 人型动画重新定位,动画角色的运动控制可以被所有的角色模型共享,即角色的外观(SkinedMesh)和运动(Animator)是分离的,它们互相组合之后形成最终的动画. 用于编辑动画状态的的简化工作流程,即动画控制器. 方便预览动画片段,以及片段之间的插值过渡. 这使得动画师可以独立