上一篇文章 《Kotlin + Netty 在 Android 上实现 Socket 的服务端》 ,曾经介绍的 NettyServer 其实只存了最后一次使用的 Channel。
Channel 是 Netty 网络操作抽象类,包括网络的读、写、发起连接、链路关闭等,它是 Netty 网络通信的主体。
在现实的开发中,服务端可能需要的是保存多个 Channel,例如存放到 ConcurrentHashMap。
当客户端连上服务端时,通过 NettyServer 的 addChannel() 将 channel 添加到 Map 中。当客户端断开服务端时,通过 NettyServer 的 removeChannel() 将 channel 从 Map 中移除。
为了安全考虑,服务端可能会主动断开某个 channel,则通过 NettyServer 的 disConnectChannel() 实现。
由于 App 中存在多个 Activity 会用到 Netty 的相关服务例如接受来自客户端的消息、发送消息到客户端,所以采用 Service 方式来启动 Netty 服务端是一种比较好的选择。
Service 跟 Activity 的交互也可以借助 EventBus 进行通信。
在使用 NettyService 时,发现会遇到如下的异常:
NettyService 是通过 startService() 启动,所以会调用 onStartCommand()。而使用 Kotlin 在创建 Service 时,默认的 onStartCommand() 方法是这样的:
但是 intent 存在为空的可能性,需要改成:
客户端和服务端之间传递的消息类型是 String 类型。即便是这样,还是要稍微定义一下 Message 的格式。
例如:
封装一个 NettyManager,它是单例,用于专门发送消息给客户端。
其中 sendMsg(msg: ()->String) 方法,它的参数是函数类型。将函数作为参数,可扩展性会更强。
Kotlin 的函数是第一等公民,函数就是对象,这是 Kotlin 作为函数式编程语言的重要特性。对象可以直接赋值给变量、可以作为某个函数的参数、也可以作为别的函数的返回值,那么函数也可以。
服务端发送消息给客户端:
本文是上一篇 《Kotlin + Netty 在 Android 上实现 Socket 的服务端》 的延续,介绍了如何做一个 Android 的 Netty 服务端、踩过的坑,以及如何封装消息。
关注【Java与Android技术栈】
更多精彩内容请 关注 :