WebSocket是一种协议,可通过TCP连接启用双向持久通信通道。它用于聊天,股票报价,游戏等应用程序,以及您希望在Web应用程序中具有实时功能的任何位置。

当你需要直接使用套接字连接直接工作时,使用 WebSockets。例如,你可能需要在实时游戏中的最好的性能。

首先,阅读 kataras/neffos(https://github.com/kataras/neffos/wiki) 的介绍,掌握这个为net/httpiris 构建的 websocket 库。

它在安装 iris 时就已经预装了,但是你也可以使用下面的命令单独安装:

  1. $ go get github.com/kataras/neffos@latest

继续阅读怎么注册neffos websockets 服务器到你的 iris 程序中。

这里可以查看一系列全面的使用websockets的示例:

  1. https://github.com/kataras/iris/tree/master/_examples/websocket

iris/websocket 子包仅包含iris 特定的为 neffos websockets 准备的迁移器(migrations,不知咋翻译)和助手。

例如,为了获得请求的 context 权限,你可以在处理器或者回调函数中调用 websocket.GetContext(conn)来获取。

  1. // GetContext从一个websocket连接中返回一个iris.Context
  2. func GetContext(c *neffos.Conn) Context

使用 websocket.Handler 注册 websocket neffos.Server 到一个路由中。

  1. // IDGenerator is an iris-specific IDGenerator for new connections.
  2. type IDGenerator func(Context) string
  3. // Handler returns an Iris handler to be served in a route of an Iris application.
  4. // Accepts the neffos websocket server as its first input argument
  5. // and optionally an Iris-specific `IDGenerator` as its second one.
  6. func Handler(s *neffos.Server, IDGenerator ...IDGenerator) Handler

使用:

  1. import (
  2. "github.com/kataras/neffos"
  3. "github.com/kataras/iris/v12/websocket"
  4. )
  5. // [...]
  6. onChat := func(ns *neffos.NSConn, msg neffos.Message) error {
  7. ctx := websocket.GetContext(ns.Conn)
  8. // [...]
  9. return nil
  10. }
  11. app := iris.New()
  12. ws := neffos.New(websocket.DefaultGorillaUpgrader, neffos.Namespaces{
  13. "default": neffos.Events {
  14. "chat": onChat,
  15. },
  16. })
  17. app.Get("/websocket_endpoint", websocket.Handler(ws))

websocket 控制器

Iris具有一种通过Go结构注册websocket事件的简单方法。 Websocket控制器是MVC功能的一部分。

Iris 提供了 iris/mvc/Application.HandleWebsocket(v interface{}) *neffos.Struct 来注册控制器到一个存在的 iris MVC程序中(提供功能齐全的依赖项注入容器,用于请求值和静态服务)。

  1. // HandleWebsocket handles a websocket specific controller.
  2. // Its exported methods are the events.
  3. // If a "Namespace" field or method exists then namespace is set,
  4. // otherwise empty namespace will be used for this controller.
  5. //
  6. // Note that a websocket controller is registered and ran under
  7. // a connection connected to a namespace
  8. // and it cannot send HTTP responses on that state.
  9. // However all static and dynamic dependencies behave as expected.
  10. func (*mvc.Application) HandleWebsocket(controller interface{}) *neffos.Struct

我们来看看使用例子,我们想要通过我们的控制器方法绑定 OnNamespaceConnectedOnNamespaceDisconnect 内置的实现和一个自定义的 OnChat 事件。

  1. 我们创建一个控制器,声明 NSConn 类型字段为 stateless,然后写我们需要的方法。

    1. type websocketController struct {
    2. *neffos.NSConn `stateless:"true"`
    3. Namespace string
    4. Logger MyLoggerInterface
    5. }
    6. func (c *websocketController) OnNamespaceConnected(msg neffos.Message) error {
    7. return nil
    8. }
    9. func (c *websocketController) OnNamespaceDisconnect(msg neffos.Message) error {
    10. return nil
    11. }
    12. func (c *websocketController) OnChat(msg neffos.Message) error {
    13. return nil
    14. }

    Iris 足够聪明,通过 Namespace string 结构体字段规定的命名空间来注册控制器方法作为事件函数, 或者你可以创建一个控制器方法 Namespace() string {return "default"},或者使用 HandleWebsocket 的返回值的 SetNamespace("default"),这取决于你。

  2. 我们将MVC应用程序目标初始化为websocket端点,就像我们以前使用常规HTTP控制器进行HTTP路由一样。

  1. ```go
  2. import (
  3. // [...]
  4. "github.com/kataras/iris/v12/mvc"
  5. )
  6. // [app := iris.New...]
  7. mvcApp := mvc.New(app.Party("/websocket_endpoint"))
  8. ```
  1. 注册我们的依赖项(如果有的话)

    1. mvcApp.Register(
    2. &prefixedLogger{prefix: "DEV"},
    3. )
  1. 我们注册一个或者多个websocket 控制器,每个控制器匹配一个namespace(只需一个就足够了,因为在大多数情况下,您不需要更多,但这取决于您的应用程序的需求和要求)。

    1. mvcApp.HandleWebsocket(&websocketController{Namespace: "default"})

    接下来,我们通过将mvc应用程序作为连接处理程序映射到websocket服务器来继续处理(一个websocket服务器可以在多个mvc应用上使用,通过 neffos.JoinConnHandlers(mvcApp1, mvcApp2))。

    1. websocketServer := neffos.New(websocket.DefaultGorillaUpgrader, mvcApp)
  2. 最后一步是通过普通的 .Get 方法将该服务器注册到我们的端点。

    1. mvcApp.Router.Get("/", websocket.Handler(websocketServer))