Unity使用webSocket与服务器通信(三)——C#服务端(Fleck)与Unity客户端( NativeWebSocket)传输多种数据数据

这篇具有很好参考价值的文章主要介绍了Unity使用webSocket与服务器通信(三)——C#服务端(Fleck)与Unity客户端( NativeWebSocket)传输多种数据数据。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、通信时会传输哪些内容

  • 1、字符串数据
    简单的字符串:比如登录请求信息,登录结果返回的信息。
    用json系列化的字符串:比如上传一个表到服务器,让它写入到数据库中。
    读取文件的时候,读取的是string内容。

  • 2、二进制数据
    比如传输的是文件:例如myword.doc,myexcel.xls或者是assetboundle文件。
    比如上传实验报告,生成实验报告并下载等。
    读取文件的时候,直接读取字节码。

二、Unity(NativeWebSocket)和服务端(Fleck)怎么约定要传输的数据格式

Unity使用webSocket与服务器通信(三)——C#服务端(Fleck)与Unity客户端( NativeWebSocket)传输多种数据数据

1、Unity(NativeWebSocket)发送和接收信息的API有哪些?

  • 发送字符串
    SendText(string message)
  • 发送二进制
    Send(byte[] bytes)
  • 接收字符串【无】
    OnMessage(string : msg)
  • 接收二进制
    OnMessage(bytes : byte[])

2、服务器发送string和byte[]给Unity时,Unity如何处理?

  • Fleck发送string,使用Send(message:string)
  • Fleck发送二进制,使用Send(bytes:byte[])
  • Unity客户端统一使用OnMessage(bytes : byte[])进行数据的接收
    Unity需要识别这个包是什么内容:字符串指令,系列化的json字符串,不同种类的二进制文件…等等!

3、传输的数据格式

Unity使用webSocket与服务器通信(三)——C#服务端(Fleck)与Unity客户端( NativeWebSocket)传输多种数据数据

4、服务器和客户端信息来往说明

Unity使用webSocket与服务器通信(三)——C#服务端(Fleck)与Unity客户端( NativeWebSocket)传输多种数据数据

5、接收和发送的关键部分

(1)、客服端发送信息

  • 发送json文件到服务器
var jsonString = JsonUtility.ToJson(myScores); //myScores 预先定义的得分信息
websocket.SendText($"JSONSCOR{jsonString}");
  • 发送字符串指令到服务器
/// <summary>
/// 命令字符串
/// </summary>
/// <param name="text">命令字符串</param>
/// <returns></returns>
public async UniTask SendCommand(string cmdText)
{
    //传输时自动在前面添加[COMD]
    var msg = $"COMD{cmdText}";
    await websocket.SendText(msg);
}
  • 发送二进制文件到服务器
/// <summary>
/// 发送文件
/// </summary>
/// <param name="file">file.extend</param>
/// <param name="data">byte[]数据</param>
/// <returns>成功与否</returns>
public async UniTask<bool> SendBinary(string fileName,byte[] data)
{
    Debug.Log($"即将发送数据:{fileName} {data.Length}");
    var rtn = false;
    if (fileName.Length > 30)
    {
        Debug.Log("文件名不能超过30个字符");
        rtn = false;
    }
    else
    {
        var head = Encoding.UTF8.GetBytes("BINA");                         
        var fileNameBytes = Encoding.UTF8.GetBytes(fileName.PadRight(30)); 
        var allData = new List<byte>();                                         
        allData.AddRange(head);             //头
        allData.AddRange(fileNameBytes);    //文件名称
        allData.AddRange(data);             //文件数据
        await websocket.Send(allData.ToArray());
        rtn = true;
    }
    return true;
}

(2)、客户端向服务器发送下载请求,并等待数据到达

  • 发送【COMDdown#shiYanBaoGao.docx】
  • 等待二进制数据下载
  • 保存文件到本地
//下载文件
downLoadBtn.onClick.AddListener(async () =>
{
    //【1】文件名
    var file = "shiYanBaoGao.docx";

    Debug.Log("从服务器下载文件");
    //COMD + down + # + shiYanBaoGao.docx

    //【2】请求下载实验报告
    var cmdText = $"COMDdown#{file}";    //[COMD][down][#][shiYanBaoGao.docx]
    await Connection.instance.websocket.SendText(cmdText);
    
    //【3】等待接收实验报告
    var data = await Connection.instance.ReceiveBinaryAsync(file);

    //【4】保存文件
    Debug.Log($"收到文件{file},大小为{data.Length}");
    FileSave.instance.SaveFileBytes(file,data);
});

(3)、客户端从服务器下载时的异步等待实现

客户端申请下载某个文件的时候逻辑:

  • 客户端创建下载任务
  • 客户端收到下载数据时判断是否是某个任务的下载需求,是则把收到的数据写入该任务缓冲里面
  • 下载完成后读取收到的数据,并从列表中删除该任务

任务列表的定义:

/// <summary>
/// 下载任务列表: 客户端申请下载某个文件的时候使用。
///  private List<DownFileTask> DownFileTasks = new List<DownFileTask>();
/// </summary>
[Serializable]
public class DownFileTask
{
    /// <summary>
    /// 任务ID
    /// </summary>
    public int taskID;

    /// <summary>
    /// 要下载的文件的名字:
    /// </summary>
    public string fileName;

    /// <summary>
    /// 下载状态:false-未下载,true-下载成功
    /// </summary>
    public bool state;

    /// <summary>
    /// 文件的数据:二进制信息
    /// </summary>
    public List<byte> data;
}

异步等待下载文件:

/// <summary>
/// 等待接收文件
/// </summary>
/// <param name="fileName">文件名</param>
/// <returns></returns>
public async UniTask<byte[]> ReceiveBinaryAsync(string fileName)
{
    //【1】创建下载任务
    var taskId = CreatTask(fileName, ref DownFileTasks);

    //【2】OnMessage(bytes[])+ ()=>{}中更新,收到文件,写入数据
    //在ParseBytes()里
    
    Debug.Log(DownFileTasks.Where(x => x.taskID == taskId).All(x => x.state));
    Debug.Log("开始等待下载......");

    //【3】等待下载
    await UniTask.WaitUntil
    (
        () => DownFileTasks.Where(x => x.taskID == taskId).All(x => x.state) == true
    );

    //【4】提取数据
    Debug.Log("提取数据......");
    var data = DownFileTasks.First(x => x.taskID == taskId).data;

    //【5】删除下载任务
    Debug.Log("删除下载任务......");
    DeleteTask(taskId, ref DownFileTasks);

    //【6】返回数据
    return data.ToArray();
}

6、客户端socket的主要事件绑定

  • 连接打开时…
  • 连接出错时…
  • 连接关闭时…
  • 收到二进制数据时…
/// <summary>
/// 连接服务器
/// </summary>
/// <param name="ip">服务器ip</param>
/// <param name="port">服务器端口号</param>
/// <returns></returns>
async UniTask<bool> ConnectServer(string ip, int port)
{
    bool rtn = false;
    try
    {
        //websocket = new WebSocket("ws://192.168.0.137:8081");
        Debug.Log($"ws://{ip}:{port}");
        websocket = new WebSocket($"ws://{ip}:{port}");

        //连接打开时...
        websocket.OnOpen += () =>
        {
            hasConnected = true;

            userID = iptfdUsername.text;
            Debug.Log("Connection open!");
            textLog.text = $"Connection open! {Time.realtimeSinceStartup} {Environment.NewLine} {textLog.text}";
            websocket.SendText($"COMDname#{userID}"); //发送用户id
        };

        //连接出错时...
        websocket.OnError += (e) =>
        {
            Debug.Log("Error! " + e);
            textLog.text = $"Error:{e} {Time.realtimeSinceStartup} {Environment.NewLine} {textLog.text}";
        };

        //连接关闭时...
        websocket.OnClose += (e) =>
        {
            hasConnected = false;
            Debug.Log("连接被关闭了!");
            textLog.text = $"连接被关闭了! {Time.realtimeSinceStartup} {Environment.NewLine} {textLog.text}";
        };

        //收到二进制数据时...
        websocket.OnMessage += (bytes) =>
        {
            //解析数据
            ParseBytes(bytes);
        };

        //开始连接
        await websocket.Connect();
        rtn = true;
    }
    catch (Exception e)
    {
        Debug.Log($"连接服务器出错:{e.Message}");
        textLog.text = $"连接服务器出错:{e.Message}";
        rtn = false;
    }
    return rtn;
}

7、服务器端socket的主要事件绑定

  • 连上时…
  • 断开时…
  • 收到字符串数据时…
  • 收到二进制数据时…
//var server = new WebSocketServer("ws://192.168.0.137:8081");  
var server = new WebSocketServer($"ws://{ip}:{port}");
server.Start(socket =>
{
    //连上ss
    socket.OnOpen = () =>
    {
        this.Invoke(new Action(() =>
        {
            //textBoxLog.Text += $"有新用户连入:{socket.ConnectionInfo.ClientIpAddress} {Environment.NewLine} {textBoxLog.Text}";
            AddText($"有新用户连入:{socket.ConnectionInfo.ClientIpAddress}");
        }));
   
        //报错的写法
        //textBoxLog.Text = $"有新用户连入:{socket.ConnectionInfo.ClientIpAddress} \n {textBoxLog.Text}";
        //SetTextLog($"有新用户连入:{socket.ConnectionInfo.ClientIpAddress}");

        Debug.WriteLine($"有新用户连入:{socket.ConnectionInfo.ClientIpAddress}");

        //回复一个信息
        //SendCommand(socket);
    };

    //断开
    socket.OnClose = () =>
    {
        Debug.WriteLine($"用户断开连接:{socket.ConnectionInfo.ClientIpAddress}");
        this.Invoke(new Action(() =>
        {
            AddText($"用户断开连接:{socket.ConnectionInfo.ClientIpAddress}");
        }));
        UserSockets.First(x => x.socket.ConnectionInfo.Id == socket.ConnectionInfo.Id).connected = false;
    };

    //收到string信息
    socket.OnMessage = message =>
    {
        Debug.WriteLine($"收到一条消息,来自:{socket.ConnectionInfo.ClientIpAddress}");
        Debug.WriteLine(message);

        this.Invoke(new Action(() =>
        {
            AddText($"收到一条消息,来自:{socket.ConnectionInfo.ClientIpAddress}");
            AddText($"{message}");
        }));

        //解析客户端字符串命令
        ParseString(message,socket);
    };

    //收到二进制信息
    socket.OnBinary = bytes =>
    {
        var userName = UserSockets.First(x => x.socket.ConnectionInfo.Id == socket.ConnectionInfo.Id)
            .userID;
        Debug.WriteLine($"收到二进制数据,长度为{bytes.Length}Bytes,来自ip:{socket.ConnectionInfo.ClientIpAddress},userID ={userName}");
        
        this.Invoke(new Action(() =>
        {
            AddText($"收到二进制数据,长度为{bytes.Length}Bytes,来自ip:{socket.ConnectionInfo.ClientIpAddress},userID ={userName}");
        }));

        var head = Encoding.UTF8.GetString(bytes.Take(4).ToArray());

        switch (head)
        {
            case "BINA":
                //收到二进制文件
                ParseBinaryFile(bytes,socket);
                break;

            case "other":
                //
                break;

            default:
                //
                break;
        }
    };
});

三、todo

实时传输语音和视频文章来源地址https://www.toymoban.com/news/detail-402820.html

到了这里,关于Unity使用webSocket与服务器通信(三)——C#服务端(Fleck)与Unity客户端( NativeWebSocket)传输多种数据数据的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C#知识点-13(进程、多线程、使用Socket实现服务器与客户端通信)

    进程 定义:每一个正在运行的应用程序,都是一个进程  进程不等于正在运行的应用程序。而是为应用程序的运行构建一个运行环境 多线程 这段代码在执行完成之前,程序会被卡死(不能操作程序,包括关闭窗口)。因为我们程序在做一些耗时操作的时候,如果主线程去执

    2024年02月22日
    浏览(93)
  • JavaWeb-WebSocket浏览器服务器双向通信

    WebSocket是基于TCP的一种新的网络协议。它实现了浏览器与服务器 全双工通信 —浏览器和服务器只需要完成一次握手,两者之间就可以创建 持久性 的连接,并进行双向数据传输。 HTTP传输 WebSocket传输 HTTP协议和WebSocket协议的对比: HTTP是短连接,WebSocket是长连接 HTTP通信是单向

    2024年01月21日
    浏览(48)
  • python模块websockets,浏览器与服务器之间的双向通信

    一、简介 WebSocket是一种在Web浏览器和服务器之间进行实时双向通信的协议。它通过建立一条持久的连接,允许服务器主动向客户端推送数据,实现实时性和双向通信的能力。 与传统的HTTP请求-响应模式不同,WebSocket提供了一个长时间运行的连接,可以在客户端和服务器之间进

    2024年02月21日
    浏览(44)
  • C#与西门子PLC1500的ModbusTcp服务器通信3--搭建ModbusTcp服务器

     注意,这个IP地址必须与西门子虚拟网卡的IP地址及虚拟机的网卡IP地址同一网段           找到程序块main,找到右边的指令,找到通信,找到其它,拖到MB_SERVER到程序段1中    重点看mb_hold_reg和connect参数,disconnet为false表示被动连接,意思是说服务器等待客户机来连接,而

    2024年02月11日
    浏览(47)
  • OPC通信从入门到精通_2_OPC通信详解和C#客户端编程(OPC基础概念;OPC通信仿真(KepServer作为OPC服务器;使用Modbus Slave和另外软件仿真2个PLC设备);C#程序)

    OPC诞生缘由:OPC诞生之前,软件工程师是不了解硬件和协议的 OPC解决的是软件和硬件之间的问题,让软件工程师无需了解协议及底层硬件,例如串口协议等 OPC起到了桥梁的作用:软件工程师对接OPC,OPC对接硬件 OPC是一种通讯方式,落到实处就是一个软件,就需要开发相应的

    2024年02月05日
    浏览(75)
  • C#与西门子PLC1500的ModbusTcp服务器通信1--项目背景

    最近在一个120万元的项目中,涉及到modbustcp通信,我作为软件总工负责项目的通信程序开发,modbus是一个在工业自动化领域中的通信协议,可以是modbusrtu,modbusascii,modbustcp三个形式,具体来说是三个不同的数据包结构,具体的细节请读者自行熟悉,这里只讲项目中应用过程

    2024年02月12日
    浏览(51)
  • Unity-UDP-客户端/服务器通信功能

    这里简单实现客户端和服务器,复杂的实现需要和前几篇文章的TCP一样,管理多个链接过来的客户端,这里只有一个。需要自己封装类似listener来管理多个链接过来的设备,每次都缓存ReceiveAsync收到消息的中的RemoteEndPoint地址端口,统一管理发送接收消息。 https://zhidao.baidu.c

    2024年02月11日
    浏览(66)
  • C#与西门子PLC1500的ModbusTcp服务器通信2--ModbusTcp协议

    Modbus TCP是近年来越来越流行的工业控制系统通信协议之一,与其他通信协议相比,Modbus TCP通信速度快、可靠性高、兼容性强、适用于模拟或数字量信号的传输,阅读本文前你必须比较熟悉Modbus协议,了解tcp网络。 Modbus TCP是一种以太网协议,它将Modbus通信协议封装在TCP/IP包内

    2024年02月11日
    浏览(46)
  • C# Socket通信从入门到精通(16)——单个同步UDP服务器监听多个客户端C#代码实现

    我们在开发UDP通信程序时,有时候我们也需要开发UDP服务器程序,这个服务器只需要和一个客户端实现通信,比如这篇博文C# Socket通信从入门到精通(15)——单个同步UDP服务器监听一个客户端C#代码实现,但是在实际项目中有的时候需要和多个客户端进行通信,这时和一个客

    2024年01月22日
    浏览(64)
  • C# Socket通信从入门到精通(15)——单个同步UDP服务器监听一个客户端C#代码实现

    我们在开发UDP通信程序时,除了开发UDP客户端程序,有时候我们也需要开发UDP服务器程序,这在实际项目中是经常会遇到的,所以说掌握UDP服务器程序的开发是一项必备的技能,尤其在上位机软件开发领域,掌握UDP服务器程序的开发是走向高级工程师的必经之路,也是面试必

    2024年02月03日
    浏览(60)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包