当前位置:   article > 正文

Unity web聊天通讯功能开发(1)_unity besthttp websocket

unity besthttp websocket

注:发文章我不像某些大咖只发大概思路,每一步我的操作我都会写下来,如果实在看不懂就去下载我的案例哈,本文章只研究下如何互发文字通讯,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,各代码如下:

  1. using SuperSocket.SocketBase;
  2. using SuperWebSocket;
  3. using System;
  4. using System.Collections.Generic;
  5. class Program
  6. {
  7. public static List<ClientController> clientControllerList = new List<ClientController>();
  8. static void Main(string[] args)
  9. {
  10. // Console.WriteLine("Press any key to start the WebSocketServer!");
  11. //Console.ReadKey();
  12. // Console.WriteLine();
  13. var appServer = new WebSocketServer();
  14. //Setup the appServer
  15. if (!appServer.Setup(2012)) //Setup with listening port
  16. {
  17. Console.WriteLine("Failed to setup!");
  18. Console.ReadKey();
  19. return;
  20. }
  21. appServer.NewSessionConnected += delegate (WebSocketSession session)
  22. {
  23. // Console.WriteLine("新玩家加入: " + session.SessionID);
  24. // session.Send("新玩家加入: " + session.SessionID);
  25. };
  26. appServer.SessionClosed += delegate (WebSocketSession session, CloseReason value)
  27. {
  28. for (int i = 0; i < clientControllerList.Count; i++)
  29. {
  30. if (session.SessionID == clientControllerList[i].session.SessionID)
  31. {
  32. ClientController client = clientControllerList[i];
  33. client .SendMessageDataToAllClientWithOutSelf(client.nickName + "离开聊天室");
  34. Console.WriteLine(client.nickName+ "离开聊天室");
  35. clientControllerList.Remove(clientControllerList[i]);
  36. return ;
  37. }
  38. }
  39. };
  40. appServer.NewMessageReceived += delegate (WebSocketSession session, string value)
  41. {
  42. MessageData data = LitJson.JsonMapper.ToObject<MessageData>(value);
  43. ClientController clientController =GetClient(session);
  44. string msg = "";
  45. switch (data.msgType)
  46. {
  47. case MessageType.Login://如果是登陆消息
  48. clientController.nickName = data.nickname;
  49. // session.Send("玩家加入: " + data.name);
  50. clientControllerList.Add(clientController);
  51. msg = clientController.nickName + "加入聊天室";
  52. Console.WriteLine(clientController.nickName + "加入聊天室");
  53. break;
  54. case MessageType.Chat://如果是聊天消息
  55. Console.WriteLine(clientController.nickName + "说: " + data.msg);
  56. data.nickname = clientController.nickName;
  57. msg = LitJson.JsonMapper.ToJson(data);
  58. break;
  59. case MessageType.LogOut://客户端请求退出
  60. Console.WriteLine(clientController.nickName + "离开聊天室");
  61. clientControllerList.Remove(clientController);
  62. msg = clientController.nickName + "离开聊天室";
  63. break;
  64. }
  65. clientController.SendMessageDataToAllClientWithOutSelf(msg);
  66. };
  67. Console.WriteLine();
  68. //Try to start the appServer
  69. if (!appServer.Start())
  70. {
  71. Console.WriteLine("Failed to start!");
  72. Console.ReadKey();
  73. return;
  74. }
  75. Console.WriteLine("The server started successfully, press key 'q' to stop it!");
  76. while (Console.ReadKey().KeyChar != 'q')
  77. {
  78. Console.WriteLine();
  79. continue;
  80. }
  81. //Stop the appServer
  82. appServer.Stop();
  83. Console.WriteLine();
  84. Console.WriteLine("The server was stopped!");
  85. Console.ReadKey();
  86. }
  87. public static ClientController GetClient(WebSocketSession session)
  88. {
  89. for (int i = 0; i < clientControllerList.Count; i++)
  90. {
  91. if (session.SessionID == clientControllerList[i].session.SessionID)
  92. {
  93. return clientControllerList[i];
  94. }
  95. }
  96. return new ClientController(session);
  97. }
  98. }
  1. using SuperWebSocket;
  2. using System;
  3. class ClientController
  4. {
  5. /// <summary>
  6. /// 用户链接的通道
  7. /// </summary>
  8. public WebSocketSession session;
  9. /// <summary>
  10. /// 昵称
  11. /// </summary>
  12. public string nickName;
  13. //接收的线程
  14. public ClientController(WebSocketSession socket)
  15. {
  16. session= socket;
  17. }
  18. /// <summary>
  19. /// 广播消息,排除掉自己
  20. /// </summary>
  21. /// <param name="data"></param>
  22. public void SendMessageDataToAllClientWithOutSelf(string data)
  23. {
  24. //5 i=3
  25. for (int i = 0; i < Program.clientControllerList.Count; i++)
  26. {
  27. if (Program.clientControllerList[i] != this)
  28. {
  29. Program.clientControllerList[i].SendToClient(data);
  30. }
  31. }
  32. }
  33. void SendToClient(string data)
  34. {
  35. session.Send(data);
  36. }
  37. }
  1. /// <summary>
  2. /// 简单的协议类型
  3. /// </summary>
  4. public enum MessageType
  5. {
  6. Chat = 0,//聊天
  7. Login = 1,//登陆
  8. LogOut = 2,//登出
  9. }
  10. /// <summary>
  11. /// 消息体
  12. /// </summary>
  13. public class MessageData
  14. {
  15. /// <summary>
  16. /// 消息类型
  17. /// </summary>
  18. public MessageType msgType;
  19. /// <summary>
  20. /// 消息内容
  21. /// </summary>
  22. public string msg;
  23. public string nickname;
  24. }

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

 

 4.客户端代码

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

  1. using LitJson;
  2. /// <summary>
  3. /// 简单的协议类型
  4. /// </summary>
  5. public enum MessageType
  6. {
  7. Chat = 0,//聊天
  8. Login = 1,//登陆
  9. LogOut = 2,//登出
  10. }
  11. /// <summary>
  12. /// 消息体
  13. /// </summary>
  14. public class MessageData
  15. {
  16. /// <summary>
  17. /// 消息类型
  18. /// </summary>
  19. public MessageType msgType;
  20. /// <summary>
  21. /// 消息内容
  22. /// </summary>
  23. public string msg;
  24. public string nickname;
  25. }
  1. using System;
  2. using UnityEngine;
  3. using BestHTTP;
  4. using BestHTTP.WebSocket;
  5. using UnityEngine.UI;
  6. using BestHTTP.Examples.Helpers;
  7. namespace BestHTTP.Examples.Websockets
  8. {
  9. public class WebSocketTest : BestHTTP.Examples.Helpers.SampleBase
  10. {
  11. // [SerializeField]
  12. // [Tooltip("The WebSocket address to connect")]
  13. private string address = "ws://192.168.2.50:2012";
  14. [SerializeField]
  15. private InputField name_input;
  16. [SerializeField]
  17. private InputField content_input;
  18. [SerializeField]
  19. private ScrollRect _scrollRect;
  20. [SerializeField]
  21. private RectTransform _contentRoot;
  22. [SerializeField]
  23. private TextListItem _listItemPrefab;
  24. [SerializeField]
  25. private int _maxListItemEntries = 100;
  26. #pragma warning restore
  27. /// <summary>
  28. /// Saved WebSocket instance
  29. /// </summary>
  30. WebSocket.WebSocket webSocket;
  31. public GameObject loginGo;
  32. public GameObject chatGo;
  33. protected override void Start()
  34. {
  35. base.Start();
  36. }
  37. public void LoginIn()
  38. {
  39. if (name_input.text == "" || name_input.text == null)
  40. return;
  41. // Create the WebSocket instance
  42. this.webSocket = new WebSocket.WebSocket(new Uri(address));
  43. #if !UNITY_WEBGL
  44. this.webSocket.StartPingThread = true;
  45. #if !BESTHTTP_DISABLE_PROXY
  46. if (HTTPManager.Proxy != null)
  47. this.webSocket.InternalRequest.Proxy = new HTTPProxy(HTTPManager.Proxy.Address, HTTPManager.Proxy.Credentials, false);
  48. #endif
  49. #endif
  50. // Subscribe to the WS events
  51. this.webSocket.OnOpen += OnOpen;
  52. this.webSocket.OnMessage += OnMessageReceived;
  53. this.webSocket.OnClosed += OnClosed;
  54. this.webSocket.OnError += OnError;
  55. // Start connecting to the server
  56. this.webSocket.Open();
  57. // AddText("Connecting...");
  58. }
  59. public void Chat()
  60. {
  61. if (content_input.text == "" || content_input.text == null)
  62. return;
  63. MessageData data = new MessageData();
  64. data.msgType = MessageType.Chat;
  65. data.msg = content_input.text;
  66. string json = JsonUtility.ToJson(data);
  67. webSocket.Send(json);
  68. ChatItem chatItem = (ChatItem)AddText(string.Format(" <color=yellow>我:</color>\n{0}",data.msg));
  69. chatItem.AddLeftPadding(20);
  70. chatItem.SetTextAlignment(TextAnchor.MiddleRight);
  71. }
  72. public void LoginOut()
  73. {
  74. MessageData data = new MessageData();
  75. data.msgType = MessageType.LogOut;
  76. data.msg = "退出";
  77. string json = JsonUtility.ToJson(data);
  78. webSocket.Send(json);
  79. webSocket.Close(1000, "Bye!");
  80. webSocket.OnOpen -= OnOpen;
  81. webSocket.OnMessage -= OnMessageReceived;
  82. webSocket.OnClosed -= OnClosed;
  83. webSocket = null;
  84. AddText("Closing!");
  85. loginGo.SetActive(true);
  86. chatGo.SetActive(false);
  87. }
  88. #region WebSocket Event Handlers
  89. /// <summary>
  90. /// Called when the web socket is open, and we are ready to send and receive data
  91. /// </summary>
  92. void OnOpen(WebSocket.WebSocket ws)
  93. {
  94. AddText("WebSocket Open!");
  95. MessageData data = new MessageData();
  96. data.msgType = MessageType.Login;
  97. data.nickname = name_input.text;
  98. string json = JsonUtility.ToJson(data);
  99. webSocket.Send(json);
  100. loginGo.SetActive(false);
  101. chatGo.SetActive(true);
  102. }
  103. /// <summary>
  104. /// Called when we received a text message from the server
  105. /// </summary>
  106. void OnMessageReceived(WebSocket.WebSocket ws, string message)
  107. {
  108. try
  109. {
  110. MessageData data = JsonUtility.FromJson<MessageData>(message);
  111. AddText(string.Format(" <color=yellow>{0}:</color>\n{1}", data.nickname,data.msg))
  112. .AddLeftPadding(20);
  113. }
  114. catch (System.Exception ex)
  115. {
  116. AddText(string.Format(" <color=yellow>{0}</color>", message))
  117. .AddLeftPadding(20);
  118. }
  119. }
  120. /// <summary>
  121. /// Called when the web socket closed
  122. /// </summary>
  123. void OnClosed(WebSocket.WebSocket ws, UInt16 code, string message)
  124. {
  125. AddText(string.Format("WebSocket closed! Code: {0} Message: {1}", code, message));
  126. webSocket = null;
  127. }
  128. /// <summary>
  129. /// Called when an error occured on client side
  130. /// </summary>
  131. void OnError(WebSocket.WebSocket ws, string error)
  132. {
  133. AddText(string.Format("An error occured: <color=red>{0}</color>", error));
  134. webSocket = null;
  135. }
  136. #endregion
  137. private TextListItem AddText(string text)
  138. {
  139. return GUIHelper.AddText(this._listItemPrefab, this._contentRoot, text, this._maxListItemEntries, this._scrollRect);
  140. }
  141. void OnDestroy()
  142. {
  143. if (this.webSocket != null)
  144. {
  145. this.webSocket.Close();
  146. this.webSocket = null;
  147. }
  148. }
  149. }
  150. }
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. namespace BestHTTP.Examples.Helpers
  6. {
  7. public class ChatItem : TextListItem
  8. {
  9. public void SetTextAlignment(TextAnchor textAnchor){
  10. _text.alignment=textAnchor;
  11. }
  12. }
  13. }

5.UI绑定功能

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

挂载脚本并赋值

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

 

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

 

 打包web同样适用

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

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/83010
推荐阅读
相关标签
  

闽ICP备14008679号