鸿蒙开发仓颉语言【在工程中使用Hyperion TCP框架】

avatar
作者
筋斗云
阅读量:0

3. 在工程中使用Hyperion TCP框架

3.1 导入Hyperion TCP框架的静态库

在工程的module.json中引入Hyperion TCP框架的静态库:

  "package_requires": {     "package_option": {       "hyperion_hyperion.buffer": "${path_to_hyperion_project}/build/release/hyperion/hyperion.buffer.cjo",       "hyperion_hyperion.logadapter": "${path_to_hyperion_project}/build/release/hyperion/hyperion.logadapter.cjo",       "hyperion_hyperion.objectpool": "${path_to_hyperion_project}/build/release/hyperion/hyperion.objectpool.cjo",       "hyperion_hyperion.threadpool": "${path_to_hyperion_project}/build/release/hyperion/hyperion.threadpool.cjo",       "hyperion_hyperion.transport": "${path_to_hyperion_project}/build/release/hyperion/hyperion.transport.cjo"     },     "path_option": []   }, 

3.2 TCP框架客户端和服务端支持的配置

1. 客户端和服务端都支持的配置
Socket配置
TcpSocketOptions类的属性作用
prop port: UInt16设置TCP服务端的监听端口
prop receiveBufferSize: ?Int64接收缓冲区大小
prop sendBufferSizeVal: ?Int64发送缓冲区大小
prop noDelay: ?BoolTCP_NODELAY选项
prop linger: ?DurationSO_LINGER选项
prop readTimeout: ?DurationSocket读超时时间
prop writeTimeout: ?DurationSocket写超时时间
prop idleTimeout: Duration连接空闲超时时间
Hyperion TCP框架配置
TcpSocketOptions类的属性作用默认值
prop asyncWrite: Bool是否开启每个连接一个写线程true
prop sliceExceedBuffer: Bool是否通过切片方式减少数组拷贝true
prop maxMessageSizeInBytes: Int64支持处理的消息的最大长度64M
prop bufferAllocateSize: Int64分配的ByteBuffer大小8192
* prop usePooledBufferAllocator: Bool是否将ByteBuffer池化重用false
* prop maxPooledBuffers: Int64缓存的ByteBuffer的最大数量2048

标*的为实验性质配置,目前不建议在生产环境中修改这些配置的默认值

2. 服务端特有的配置
EndpointConfig类的属性作用
prop address: String设置TCP服务端的监听地址
prop backlogSize: ?Int64backlog队列大小
prop reuseAddress: ?BoolSO_REUSE_ADDR选项
prop sendBufferSizeVal: ?Int64发送缓冲区大小
prop reusePort: ?BoolSO_REUSE_PORT选项
prop acceptTimeout: ?DurationAccept超时时间
3. 客户端特有的配置
ClientEndpointConfig类的属性作用
prop host: String设置TCP服务端的监听地址
prop minConnections: Int64连接池的最小连接数
prop maxConnections: Int64连接池的最大连接数
prop waitConnectionTimeout: Duration等待连接超时时间

3.3 实现一个回写消息的服务端

3.3.1 需求

需求: 回写客户端发送过来的字符串消息
传输报文:4字节的字符串二进制数组长度+字符串的二进制数组

长度说明
4字节使用utf8编码的字符串的Byte数组的长度
n字节使用utf8编码的字符串的Byte数组
3.3.2 服务定义

编写一个回写字符串消息的服务:

public class EchoService {      public func processMessage(message: String) {         return message     }  } 
3.3.3 实现编解码和调用服务的IoFilter

编写一个IoFilter,将入栈消息交给EchoService处理:

public class EchoHanlder <: SingularMessageIoFilter {     private let service = EchoService()      /**      * 处理入栈消息      */     public func processInboundMessage(context: IoFilterContext, session: Session, inMessage: Any): Unit {         if (let Some(text) <- inMessage as String) {             println("Received Message: ${text}")             // 调用业务处理逻辑             let result = service.processMessage(text)             context.offerMessage(result)         } else {             let exception = Exception("Only accept string message")             context.exceptionCaught(exception)         }     }      public func processInboundException(context: IoFilterContext, session: Session, ex: Exception) {         context.exceptionCaught(ex)     }      /**      *  处理出栈消息      */     public func processOutboundMessage(context: IoFilterContext, session: Session, outMessage: Any): Unit {         // 转交给下一个IoFilter处理         context.offerMessage(outMessage)     }      public func processOutboundException(context: IoFilterContext, session: Session, ex: Exception): Unit {         context.exceptionCaught(ex)     }      public func toString() {         return "EchoHanlder"     } } 

编写一个将字符串转换为二进制数组的IoFilter,由于hyperion.transport.ByteAndStringCodec已经实现该功能,可以直接选用ByteAndStringCodec
编写一个给二进制数组添加报文长度的IoFilter,由于hyperion.transport.LengthBasedFrameCodec已经实现该功能,可以直接选用LengthBasedFrameCodec

3.3.4 编写TCP服务端

编写服务端,并添加编解码和调用服务使用的IoFilter:

    let config = EndpointConfig()     config.address = "127.0.0.1"     config.port = 8090      // 服务端使用的线程池     let threadPool = ThreadPoolFactory.createThreadPool(3, 128, 4096, Duration.minute * 2)     // 创建服务端Endpoint     let tcpEndpoint = TcpEndpoint(config, threadPool)      // 使用4字节记录报文长度的编解码器     let lengthFrameEncoder = LengthBasedFrameEncoder(4)     let lengthFrameDecoder = LengthBasedFrameDecoder(4)     // 判断报文是否包含完整消息的MessageCompletedHandler     tcpEndpoint.setMessageCompletedHandler(lengthFrameDecoder)     // 解析报文长度的IoFilter     tcpEndpoint.addFilter(LengthBasedFrameCodec(lengthFrameEncoder, lengthFrameDecoder))     // 字符串和二进制数组转换的IoFilter     tcpEndpoint.addFilter(ByteAndStringCodec())     // 调用服务的IoFilter     tcpEndpoint.addFilter(EchoHanlder())      // 启动服务端Endpoint     tcpEndpoint.start() 

3.4 实现一个收发字符串消息的客户端

3.4.1 需求

需求: 向服务端发送字符串,并收取字符串响应
传输报文:4字节的字符串二进制数组长度+字符串的二进制数组

长度说明
4字节使用utf8编码的字符串的Byte数组的长度
n字节使用utf8编码的字符串的Byte数组
3.4.2 实现接收响应消息的类
public class EchoResponse {     private var exception: ?Exception = None      private var message: ?String = None      public func setException(exception: Exception) {         this.exception = exception     }      public func getException(): ?Exception {         return this.exception     }      public func setMessage(message: String) {         this.message = message     }      public func getMessage(): String {         if (let Some(ex) <- exception) {             throw ex         }          if (let Some(message) <- message) {             return message         }          throw Exception("No response message")     } } 
3.4.3 实现编解码和调用服务的IoFilter

编写一个IoFilter,将收取到的消息放入队列中,以便后续获取使用:

public class ClientHandler <: SingularMessageIoFilter {     private let messages = BlockingQueue<EchoResponse>()      public func takeMessage(): String {         let echoResponse = messages.dequeue()         return echoResponse.getMessage()     }      public func takeMessage(timeout: Duration): ?String {         if (let Some(echoResponse) <- messages.dequeue(timeout)) {             return echoResponse.getMessage()         }          return None     }      /**      * 处理入栈消息      */     public func processInboundMessage(context: IoFilterContext, session: Session, inMessage: Any): Unit {         let echoResponse = EchoResponse()         if (let Some(text) <- inMessage as String) {             echoResponse.setMessage(text)         } else {             let exception = Exception("Only accept string message")             echoResponse.setException(exception)         }          // 添加到messages队列中,不再交给下一个IoFilter处理         messages.enqueue(echoResponse)     }      public func processInboundException(context: IoFilterContext, session: Session, ex: Exception) {         let echoResponse = EchoResponse()         echoResponse.setException(ex)         // 添加到messages队列中,不再交给下一个IoFilter处理         messages.enqueue(echoResponse)     }      /**      *  处理出栈消息      */     public func processOutboundMessage(context: IoFilterContext, session: Session, outMessage: Any): Unit {         if (let Some(text) <- outMessage as String) {             // 直接发给下个IoFilter处理             context.offerMessage(text)         } else {             let exception = Exception("Only accept string message")             context.exceptionCaught(exception)         }     }      public func processOutboundException(context: IoFilterContext, session: Session, ex: Exception): Unit {         context.exceptionCaught(ex)     }      public func toString() {         return "ClientHanlder"     } } 

编写一个将字符串转换为二进制数组的IoFilter,由于hyperion.transport.ByteAndStringCodec已经实现该功能,可以直接选用ByteAndStringCodec
编写一个给二进制数组添加报文长度的IoFilter,由于hyperion.transport.LengthBasedFrameCodec已经实现该功能,可以直接选用LengthBasedFrameCodec

3.4.4 编写TCP客户端

编写服务端,并添加编解码和调用服务使用的IoFilter:

    let config = ClientEndpointConfig()     config.host = "127.0.0.1"     config.port = 8090      // 客户端使用的线程池     let threadPool = ThreadPoolFactory.createThreadPool(3, 128, 4096, Duration.minute * 2)     // 创建客户端Endpoint     let tcpEndpoint = ClientTcpEndpoint(config, threadPool)      // 使用4字节记录报文长度的编解码器     let lengthFrameEncoder = LengthBasedFrameEncoder(4)     let lengthFrameDecoder = LengthBasedFrameDecoder(4)     // 判断报文是否包含完整消息的MessageCompletedHandler     tcpEndpoint.setMessageCompletedHandler(lengthFrameDecoder)     // 解析报文长度的IoFilter     tcpEndpoint.addFilter(LengthBasedFrameCodec(lengthFrameEncoder, lengthFrameDecoder))     // 字符串和二进制数组转换的IoFilter     tcpEndpoint.addFilter(ByteAndStringCodec())     // 接收消息并缓存消息到队列中的IoFilter     let clientHandler = ClientHandler()     tcpEndpoint.addFilter(clientHandler)      // 启动客户端Endpoint     tcpEndpoint.start()      // 创建会话,并使用会话发送消息     try (session = tcpEndpoint.createSession()) {         // 发送消息,并收取对应的响应         for (i in 1..=100) {             let message = "Message${i}"             println("Send message: ${message}")             session.writeAndFlushMessage(message)             let receiveMsg = clientHandler.takeMessage()             println("Client receive message: ${receiveMsg}")         }     } 

以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!
下面是鸿蒙的完整学习路线,展示如下:
在这里插入图片描述
在这里插入图片描述
除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下

内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!

鸿蒙【北向应用开发+南向系统层开发】文档笔记

在这里插入图片描述

鸿蒙【基础+实战项目】视频

在这里插入图片描述

鸿蒙面经

在这里插入图片描述
为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自取喔!谢谢大家观看!

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!