注:发文章我不像某些大咖只发大概思路,每一步我的操作我都会写下来,如果实在看不懂就去下载我的案例哈,本文章只研究下如何互发文字通讯,web端互发图片的等我研究出来再发哈

Unity做聊天室,网上大多数都是通过socket做的,我之前也尝试了一下不难,但是最近的项目都是发布成webgl,我发现一个问题,那就是web端不支持socket,通过查找资料,我找到另一个通讯方式——websocket,先普及型websocket。

WebSocket protocol 是HTML5一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex)。一开始的握手需要借助HTTP请求完成。

1.原理:

WebSocket同HTTP一样也是应用层的协议,但是它是一种双向通信协议,是建立在TCP之上的。

2.连接过程 —— 握手过程

  • 1. 浏览器、服务器建立TCP连接,三次握手。这是通信的基础,传输控制层,若失败后续都不执行。
  • 2. TCP连接成功后,浏览器通过HTTP协议向服务器传送WebSocket支持的版本号等信息。(开始前的HTTP握手)
  • 3. 服务器收到客户端的握手请求后,同样采用HTTP协议回馈数据。
  • 4. 当收到了连接成功的消息后,通过TCP通道进行传输通信。

3.WebSocket与HTTP的关系

相同点

  • 1. 都是一样基于TCP的,都是可靠性传输协议。
  • 2. 都是应用层协议。

不同点

  • 1. WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息。HTTP是单向的。
  • 2. WebSocket是需要握手进行建立连接的。

联系

WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的。

4.WebSocket与Socket的关系

Socket其实并不是一个协议,而是为了方便使用TCP或UDP而抽象出来的一层,是位于应用层和传输控制层之间的一组接口。

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

当两台主机通信时,必须通过Socket连接,Socket则利用TCP/IP协议建立TCP连接。TCP连接则更依靠于底层的IP协议,IP协议的连接则依赖于链路层等更低层次。

WebSocket则是一个典型的应用层协议。

区别

Socket是传输控制层协议,WebSocket是应用层协议。

5.在Unity中,WebSocket比Socket更适用各个平台的开发

以下介绍下Unity发布Web,通讯功能如何做,以聊天室为案例

1.导入BestHttp插件

这个插件包含所有即使通讯方式的简单使用,下载地址为BestHttp通讯插件-C#文档类资源-CSDN下载

2.布置UI

这边我只做了两个简易界面,一个是登录界面,一个是聊天窗口界面,功能如图所示

3.构建服务端

使用VS新建项目C#控制台

通过包管理器,引用websocket和litjson相关组件

除了控制台自带的类Program,还需新建类MessageData,ClientController,各代码如下:

using SuperSocket.SocketBase;
using SuperWebSocket;
using System;
using System.Collections.Generic;class Program
{public static List<ClientController> clientControllerList = new List<ClientController>();static void Main(string[] args){// Console.WriteLine("Press any key to start the WebSocketServer!");//Console.ReadKey();// Console.WriteLine();var appServer = new WebSocketServer();//Setup the appServerif (!appServer.Setup(2012)) //Setup with listening port{Console.WriteLine("Failed to setup!");Console.ReadKey();return;}appServer.NewSessionConnected += delegate (WebSocketSession session){//  Console.WriteLine("新玩家加入: " + session.SessionID);//  session.Send("新玩家加入: " + session.SessionID);};appServer.SessionClosed += delegate (WebSocketSession session, CloseReason value){for (int i = 0; i < clientControllerList.Count; i++){if (session.SessionID == clientControllerList[i].session.SessionID){ClientController client = clientControllerList[i];client .SendMessageDataToAllClientWithOutSelf(client.nickName + "离开聊天室");Console.WriteLine(client.nickName+ "离开聊天室");clientControllerList.Remove(clientControllerList[i]);return ;}}};appServer.NewMessageReceived += delegate (WebSocketSession session, string value){MessageData data = LitJson.JsonMapper.ToObject<MessageData>(value);ClientController clientController =GetClient(session);string msg = "";switch (data.msgType){case MessageType.Login://如果是登陆消息clientController.nickName = data.nickname;//   session.Send("玩家加入: " + data.name);clientControllerList.Add(clientController);msg = clientController.nickName + "加入聊天室";Console.WriteLine(clientController.nickName + "加入聊天室");break;case MessageType.Chat://如果是聊天消息Console.WriteLine(clientController.nickName + "说: " + data.msg);data.nickname = clientController.nickName;msg = LitJson.JsonMapper.ToJson(data);break;case MessageType.LogOut://客户端请求退出Console.WriteLine(clientController.nickName + "离开聊天室");clientControllerList.Remove(clientController);msg = clientController.nickName + "离开聊天室";break;}clientController.SendMessageDataToAllClientWithOutSelf(msg);};Console.WriteLine();//Try to start the appServerif (!appServer.Start()){Console.WriteLine("Failed to start!");Console.ReadKey();return;}Console.WriteLine("The server started successfully, press key 'q' to stop it!");while (Console.ReadKey().KeyChar != 'q'){Console.WriteLine();continue;}//Stop the appServerappServer.Stop();Console.WriteLine();Console.WriteLine("The server was stopped!");Console.ReadKey();}public static ClientController GetClient(WebSocketSession session){for (int i = 0; i < clientControllerList.Count; i++){if (session.SessionID == clientControllerList[i].session.SessionID){return clientControllerList[i];}}return new ClientController(session);}
}
using SuperWebSocket;
using System;class ClientController
{/// <summary>/// 用户链接的通道/// </summary>public WebSocketSession session;/// <summary>/// 昵称/// </summary>public string nickName;//接收的线程public ClientController(WebSocketSession  socket){session= socket;}/// <summary>/// 广播消息,排除掉自己/// </summary>/// <param name="data"></param>public  void SendMessageDataToAllClientWithOutSelf(string data){//5   i=3for (int i = 0; i < Program.clientControllerList.Count; i++){if (Program.clientControllerList[i] != this){Program.clientControllerList[i].SendToClient(data);}}}void SendToClient(string data){session.Send(data);}}
/// <summary>
/// 简单的协议类型
/// </summary>
public enum MessageType
{Chat = 0,//聊天Login = 1,//登陆LogOut = 2,//登出
}
/// <summary>
/// 消息体
/// </summary>
public class MessageData
{/// <summary>/// 消息类型/// </summary>public MessageType msgType;/// <summary>/// 消息内容/// </summary>public string msg;public string nickname;
}

此时点击运行,即可运行服务端

4.客户端代码

新建类WebSocketTest,MessageData,ChatItem,代码如下:

using LitJson;
/// <summary>
/// 简单的协议类型
/// </summary>
public enum MessageType
{Chat = 0,//聊天Login = 1,//登陆LogOut = 2,//登出
}
/// <summary>
/// 消息体
/// </summary>
public class MessageData
{/// <summary>/// 消息类型/// </summary>public MessageType msgType;/// <summary>/// 消息内容/// </summary>public string msg;public string nickname;
}
using System;
using UnityEngine;
using BestHTTP;
using BestHTTP.WebSocket;
using UnityEngine.UI;
using BestHTTP.Examples.Helpers;namespace BestHTTP.Examples.Websockets
{public class WebSocketTest : BestHTTP.Examples.Helpers.SampleBase{// [SerializeField]//  [Tooltip("The WebSocket address to connect")]private string address = "ws://192.168.2.50:2012";[SerializeField]private InputField name_input;[SerializeField]private InputField content_input;[SerializeField]private ScrollRect _scrollRect;[SerializeField]private RectTransform _contentRoot;[SerializeField]private TextListItem _listItemPrefab;[SerializeField]private int _maxListItemEntries = 100;#pragma warning restore/// <summary>/// Saved WebSocket instance/// </summary>WebSocket.WebSocket webSocket;public GameObject loginGo;public GameObject chatGo;protected override void Start(){base.Start();}public void LoginIn(){if (name_input.text == "" || name_input.text == null)return;// Create the WebSocket instancethis.webSocket = new WebSocket.WebSocket(new Uri(address));#if !UNITY_WEBGLthis.webSocket.StartPingThread = true;#if !BESTHTTP_DISABLE_PROXYif (HTTPManager.Proxy != null)this.webSocket.InternalRequest.Proxy = new HTTPProxy(HTTPManager.Proxy.Address, HTTPManager.Proxy.Credentials, false);
#endif
#endif// Subscribe to the WS eventsthis.webSocket.OnOpen += OnOpen;this.webSocket.OnMessage += OnMessageReceived;this.webSocket.OnClosed += OnClosed;this.webSocket.OnError += OnError;// Start connecting to the serverthis.webSocket.Open();//   AddText("Connecting...");}public void Chat(){if (content_input.text == "" || content_input.text == null)return;MessageData data = new MessageData();data.msgType = MessageType.Chat;data.msg = content_input.text;string json = JsonUtility.ToJson(data);webSocket.Send(json);ChatItem chatItem  =  (ChatItem)AddText(string.Format(" <color=yellow>我:</color>\n{0}",data.msg));chatItem.AddLeftPadding(20);chatItem.SetTextAlignment(TextAnchor.MiddleRight);}public void LoginOut(){MessageData data = new MessageData();data.msgType = MessageType.LogOut;data.msg = "退出";string json = JsonUtility.ToJson(data);webSocket.Send(json);webSocket.Close(1000, "Bye!");webSocket.OnOpen -= OnOpen;webSocket.OnMessage -= OnMessageReceived;webSocket.OnClosed -= OnClosed;webSocket = null;AddText("Closing!");loginGo.SetActive(true);chatGo.SetActive(false);}#region WebSocket Event Handlers/// <summary>/// Called when the web socket is open, and we are ready to send and receive data/// </summary>void OnOpen(WebSocket.WebSocket ws){AddText("WebSocket Open!");MessageData data = new MessageData();data.msgType = MessageType.Login;data.nickname = name_input.text;string json = JsonUtility.ToJson(data);webSocket.Send(json);loginGo.SetActive(false);chatGo.SetActive(true);}/// <summary>/// Called when we received a text message from the server/// </summary>void OnMessageReceived(WebSocket.WebSocket ws, string message){try{MessageData data = JsonUtility.FromJson<MessageData>(message);AddText(string.Format(" <color=yellow>{0}:</color>\n{1}", data.nickname,data.msg)).AddLeftPadding(20);}catch (System.Exception ex){AddText(string.Format(" <color=yellow>{0}</color>", message)).AddLeftPadding(20);}}/// <summary>/// Called when the web socket closed/// </summary>void OnClosed(WebSocket.WebSocket ws, UInt16 code, string message){AddText(string.Format("WebSocket closed! Code: {0} Message: {1}", code, message));webSocket = null;}/// <summary>/// Called when an error occured on client side/// </summary>void OnError(WebSocket.WebSocket ws, string error){AddText(string.Format("An error occured: <color=red>{0}</color>", error));webSocket = null;}#endregionprivate TextListItem AddText(string text){return GUIHelper.AddText(this._listItemPrefab, this._contentRoot, text, this._maxListItemEntries, this._scrollRect);}void OnDestroy(){if (this.webSocket != null){this.webSocket.Close();this.webSocket = null;}}}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace BestHTTP.Examples.Helpers
{
public class ChatItem : TextListItem
{public void SetTextAlignment(TextAnchor textAnchor){_text.alignment=textAnchor;}
}
}

5.UI绑定功能

先复制一个“TextListItem”预制件,插件BestHttp里面有,然后去除它本身的脚本,挂上ChatItem脚本,成为一个新的预制件,供后面使用。

挂载脚本并赋值

将登陆按钮绑定登陆方法,发送按钮绑定发送方法

最后我们复制两个聊天系统,运行查看结果

打包web同样适用

demo:unitywebsocket聊天室案例-Unity3D文档类资源-CSDN下载

Unity web聊天通讯功能开发(1)相关推荐

  1. 微信公众平台开发(七) 聊天机器人功能开发

    一.简介 上一篇文章介绍了微信公众平台翻译功能的开发,实现了中.英.日语言互译,在实际生活中也能使用到.在接下来的这一篇文章中,我们将完成一个比较有趣的功能,那就是聊天机器人,可以在你无聊的时候陪你聊 ...

  2. 微信公众平台开发(PHP)(七) 聊天机器人功能开发

    一.简介 上一篇文章介绍了微信公众平台翻译功能的开发,实现了中.英.日语言互译,在实际生活中也能使用到.在接下来的这一篇文章中,我们将完成一个比较有趣的功能,那就是聊天机器人,可以在你无聊的时候陪你聊 ...

  3. 微信公众平台开发(23) 聊天机器人功能开发

    原文: http://www.cnblogs.com/imaker/p/5491433.html 一.简介 上一篇文章介绍了微信公众平台翻译功能的开发,实现了中.英.日语言互译,在实际生活中也能使用到 ...

  4. 基于socket.io的web聊天室

    基于socket.io的web聊天室 一. 项目介绍 该项目使用node.js作为后端服务器框架,并利用socket.io来实现web聊天室功能.socket.io是由 JavaScript 实现的基 ...

  5. Python实现web聊天室

    使用Python模块中的select模块实现web聊天室功能 select模块 Python中的select模块专注于I/O多路复用,提供了select  poll  epoll三个方法(其中后两个在 ...

  6. 关于Vue开发即时聊天类功能的经验分享(其实并不复杂)

    当下即时通讯已经成为大多数产品的主要功能,最近在工作过程中需要初步开发一个具有基础通讯功能的客服功能.根据此开发功能的过程,总结了一些开发经验与方法(使用的SDK不同,实现方法也会有比较大的差异).之 ...

  7. 网易im即时聊天php怎么接入,网易云信IM即时通讯功能接入方式与流程_如何收费_企业服务汇...

    编者按:很多企业在考虑使用网易云信提供的IM即时通讯功能,对于企业应当如何接入该功能.接入方式和流程是怎样的.应当如何收费等不太清楚.企业服务汇通过评测网易云信IM即时通讯功能来告诉你答案. 网易云信 ...

  8. 从 0 到 1 开发一个聊天通讯 服务 复盘总结

    前言 在上个月初,接到一个需求,要开发一个 聊天通讯 模块 并且 集成到 项目中的多个 入口,实现业务数据的记录追踪. 接到需求后,还挺开心,这是我第一次 搞 通讯 类的需求,之前一直是 B 端 的业 ...

  9. LayIM 3.9.1与ASP.NET SignalR实现Web聊天室快速入门(四)之ASP.NET SignalR核心功能介绍

    前言 本系列文章特点:使用ASP.NET SignalR和LayIM快速入门对接,实现一对一聊天,群聊,添加聊天群组,查找聊天记录等功能.源代码不包含LayIM的源代码,因为官方并没开源属于收费资源, ...

  10. 蓝牙聊天App设计3:Android Studio制作蓝牙聊天通讯软件(完结,蓝牙连接聊天,结合生活情景进行蓝牙通信的通俗讲解,以及代码功能实现,内容详细,讲解通俗易懂)

    前言:蓝牙聊天App设计全部有三篇文章(一.UI界面设计,二.蓝牙搜索配对连接实现,三.蓝牙连接聊天),这篇文章是:三.蓝牙连接聊天. 课程1:Android Studio小白安装教程,以及第一个An ...

最新文章

  1. 配置React的Babel 6和Webpack 2环境
  2. 什么是“可证伪性”?
  3. CG-CTF-Web-/x00
  4. 处于停机等非正常状态_一文聊透 Dubbo 优雅停机
  5. 实战:Redis 主从同步
  6. 一发就会被秒赞的句子
  7. Qt4_实现Edit菜单
  8. flask框架_Flask框架的入门:Hello world
  9. weak和assign的区别
  10. 解决DELL服务器每次开机提示F1F2,需要F1才可以进系统的方法
  11. selnium 判断页面加载完成_selenium webdriver——等待页面元素加载完成
  12. IBM人工智能系统赢得人机辩论比赛
  13. DID; PSM; DID-PSM
  14. 新计算机的windows要不要不断更新,win10一直出现无法完成更新正在撤销更改请不要关闭你的计算机,怎么办?...
  15. 计算机怎么一键返回桌面,回到桌面的快捷键是啥_快速桌面快捷键怎么操作-win7之家...
  16. 微信公众号自定义菜单CLICK返回的是大写
  17. 前沿笔记|Eva:基于AI强化学习的COVID-19检测判断模型|Nature
  18. 在SQL中char、nchar、varchar和nvarchar的区别
  19. 经方败案群9月底黎德育讲颈椎病的治疗
  20. APP测试的入门书籍有哪些?

热门文章

  1. 中国虾养殖和捕捞现状分析,养殖产量成上升趋势「图」
  2. java实现多表代替密码(维吉尼亚密码)
  3. 苹果4s怎么越狱教程_苹果手机:iPhone 11/XS系列iOS13-13.3越狱教程
  4. 【houdini vex】边界点提取与扩展
  5. 【Unity实战100例】Unity数据导出Excel表格
  6. Matlab标定工具箱使用教程
  7. arduino红外测距模块点亮一个LED灯
  8. android使用libyuv
  9. 平面设计中的网格系统pdf_小白新手想要系统学习平面设计要看哪些书?
  10. 人大金仓数据库 Windows安装教程 -kingbase8R6