使用gf框架进行websocket开发相当简单!我们以下通过实现一个简单的echo服务器来演示gf框架的websocket的使用(客户端使用HTML5实现)。示例代码:geg/net/ghttp/websocket/echo

HTML5客户端

先上H5客户端的代码

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>gf websocket echo server</title>
  5. <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">
  6. <script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
  7. </head>
  8. <body>
  9. <div class="container">
  10. <div class="list-group" id="divShow"></div>
  11. <div>
  12. <div><input class="form-control" id="txtContent" autofocus rows="6" placeholder="请输入发送内容"></div>
  13. <div><button class="btn btn-default" id="btnSend" style="margin-top:15px">发 送</button></div>
  14. </div>
  15. </div>
  16. </body>
  17. </html>
  18. <script type="application/javascript">
  19. // 显示提示信息
  20. function showInfo(content) {
  21. $("<div class=\"list-group-item list-group-item-info\">" + content + "</div>").appendTo("#divShow")
  22. }
  23. // 显示警告信息
  24. function showWaring(content) {
  25. $("<div class=\"list-group-item list-group-item-warning\">" + content + "</div>").appendTo("#divShow")
  26. }
  27. // 显示成功信息
  28. function showSuccess(content) {
  29. $("<div class=\"list-group-item list-group-item-success\">" + content + "</div>").appendTo("#divShow")
  30. }
  31. // 显示错误信息
  32. function showError(content) {
  33. $("<div class=\"list-group-item list-group-item-danger\">" + content + "</div>").appendTo("#divShow")
  34. }
  35. $(function () {
  36. var url = "ws://127.0.0.1:8199/ws";
  37. var ws = new WebSocket(url);
  38. try {
  39. // ws连接成功
  40. ws.onopen = function () {
  41. showInfo("WebSocket Server [" + url +"] 连接成功!");
  42. };
  43. // ws连接关闭
  44. ws.onclose = function () {
  45. if (ws) {
  46. ws.close();
  47. ws = null;
  48. }
  49. showError("WebSocket Server [" + url +"] 连接关闭!");
  50. };
  51. // ws连接错误
  52. ws.onerror = function () {
  53. if (ws) {
  54. ws.close();
  55. ws = null;
  56. }
  57. showError("WebSocket Server [" + url +"] 连接关闭!");
  58. };
  59. // ws数据返回处理
  60. ws.onmessage = function (result) {
  61. showWaring(" > " + result.data);
  62. };
  63. } catch (e) {
  64. alert(e.message);
  65. }
  66. // 按钮点击发送数据
  67. $("#btnSend").on("click", function () {
  68. if (ws == null) {
  69. showError("WebSocket Server [" + url +"] 连接失败,请F5刷新页面!");
  70. return;
  71. }
  72. var content = $.trim($("#txtContent").val()).replace("/[\n]/g", "");
  73. if (content.length <= 0) {
  74. alert("请输入发送内容!");
  75. return;
  76. }
  77. $("#txtContent").val("")
  78. showSuccess(content);
  79. ws.send(content);
  80. });
  81. // 回车按钮触发发送点击事件
  82. $("#txtContent").on("keydown", function (event) {
  83. if (event.keyCode == 13) {
  84. $("#btnSend").trigger("click");
  85. }
  86. });
  87. })
  88. </script>

客户端的功能很简单,主要实现了这几个功能:

  • 与服务端websocket连接状态保持及信息展示;
  • 界面输入内容并发送信息到websocket服务端;
  • 接收到websocket的返回信息后回显在界面上;

WebSocket服务端

  1. package main
  2. import (
  3. "gitee.com/johng/gf/g"
  4. "gitee.com/johng/gf/g/net/ghttp"
  5. )
  6. func main() {
  7. s := g.Server()
  8. s.BindHandler("/ws", func(r *ghttp.Request) {
  9. ws, _ := r.WebSocket()
  10. for {
  11. msgType, msg, err := ws.ReadMessage()
  12. if err != nil {
  13. return
  14. }
  15. if err = ws.WriteMessage(msgType, msg); err != nil {
  16. return
  17. }
  18. }
  19. })
  20. s.SetPort(8199)
  21. s.Run()
  22. }

可以看到,服务端的代码相当简单,这里需要着重说明的是3个地方:

  1. WebSocket方法
    websocket服务端的路由注册方式和普通的http回调函数注册方式一样,但是在接口处理中我们需要通过ghttp.Request.WebSocket方法(这里直接使用指针对象r.WebSocket())将请求转换为websocket操作,并返回一个WebSocket对象,该对象用于后续的websocket通信操作。当然,如果客户端请求并非为websocket操作时,转换将会失败,该方法会返回错误信息,使用时请注意判断方法的error返回值。
  2. ReadMessage & WriteMessage
    读取消息以及写入消息对应的是websocket的数据读取以及写入操作(ReadMessage & WriteMessage),需要注意的是这两个方法都有一个msgType的变量,表示请求读取及写入数据的类型,常见的两种数据类型为:字符串数据或者二进制数据。在使用过程中,由于接口双方都会约定统一的数据格式,因此读取和写入的msgType几乎都是一致的,所以在本示例中的返回消息时,数据类型参数直接使用的是读取到的msgType

示例结果展示

我们首先执行示例代码main.go,随后访问页面,随意输入请求内容并提交,随后在服务端关闭程序。可以看到,页面会回显提交的内容信息,并且即时展示websocket的连接状态的改变,当服务端关闭时,客户端也会即时地打印出关闭信息。

WebSocket服务 - 图1