ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

如何用 V 语言 net.jsonrpc 模块编写 JSON-RPC 服务端与客户端

如何用 V 语言 net.jsonrpc 模块编写 JSON-RPC 服务端与客户端 如何用 V 语言 net.jsonrpc 模块编写 JSON-RPC 服务端与客户端【免费下载链接】vSimple, fast, safe, compiled language for developing maintainable software. Compiles itself in 1s with zero library dependencies. Supports automatic C V translation. https://vlang.io项目地址: https://gitcode.com/GitHub_Trending/v/v本文的任务是在 V 语言项目中实现一个基于 TCP 的 JSON-RPC 2.0 服务并提供能请求、批量请求、发送通知的配套客户端。实现直接使用 V 标准库中的net.jsonrpc模块模块 README、协议结构该模块提供纯 V 实现的 JSON-RPC 2.0 clientserver支持单条/批量编解码且 Server 与 Client 都可以工作于任意io.ReaderWriter之上。完成后的效果服务端监听127.0.0.1:42228客户端通过net.dial_tcp连接后调用kv.create、kv.get等方法并收到响应。模块能力与已知限制写代码前先确认模块边界这些限制直接影响参数和错误码的设计来源vlib/net/jsonrpc/README.md仅支持 JSON-RPC 2.0与 JSON-RPC 1.0 不兼容Request/Response 的id只支持字符串Server 会自动识别批量请求以[开头的 JSON 数组并构造批量响应Server 与 Client 都接受任意io.ReaderWriter作为stream字段值因此本文示例虽然用 TCP也可以换成其他流支持jsonrpc.Interceptors拦截 event、raw Request、Request、Response、raw Response 五个事件模块自带jsonrpc.LoggingInterceptor日志实现。准备条件需要一个可用的 V 编译器。按仓库 README.md 的用法v run 文件路径会直接构建并运行程序因此无需单独编译出可执行文件即可验证示例。服务端与客户端示例代码在仓库中已有完整可运行版本服务端examples/jsonrpc/server.v客户端examples/jsonrpc/client.v下面的代码按这两个示例组织先给最短主路径再给完整多方法路由版本。编写服务端最短主路径单 Handler 服务README 给出的最小服务端是每个 TCP 连接创建一个jsonrpc.Server由单个 Handler 处理所有请求import net import net.jsonrpc fn handle_test(req jsonrpc.Request, mut wr jsonrpc.ResponseWriter) { p : req.decode_params[string]() or { wr.write_error(jsonrpc.invalid_params) return } wr.write(p) } fn handle_conn(mut conn net.TcpConn) { defer { conn.close() or {} } mut srv : jsonrpc.new_server(jsonrpc.ServerConfig{ stream: conn handler: handle_test }) srv.start() } addr : 127.0.0.1:42228 mut l : net.listen_tcp(.ip, addr)! println(TCP JSON-RPC server on ${addr} (Content-Length framing)) for { mut c : l.accept()! println(Accepted) go handle_conn(mut c) }要点说明均来自 README.md 与 server.v 源码注释ServerConfig.stream传入 TCP 连接Server.start()会循环读取该流并写回同一流传输采用 Content-Length 帧格式handler的签名固定为fn(req jsonrpc.Request, mut wr jsonrpc.ResponseWriter)每个 Handler 返回前必须且只能调用wr.write()或wr.write_error()之一否则流会卡在等待写 Response 的状态对 Notification请求不带idServer 仍会调用 Handler但会忽略写入的 Response。完整版本Router 分发多个方法真实服务通常有多个方法。jsonrpc.Router是一个方法名到 Handler 的注册表把r.handle_jsonrpc传给 Server 即可未注册的方法会自动以jsonrpc.method_not_found错误响应。完整示例 examples/jsonrpc/server.v 的结构如下节选关键部分struct KvItem { key string value string } struct KvKey { key string } #[heap] struct KvHandler { mut: store KvStore } fn (mut h KvHandler) handle_get(req jsonrpc.Request, mut wr jsonrpc.ResponseWriter) { p : req.decode_params[KvKey]() or { wr.write_error(jsonrpc.invalid_params) return } value : h.store.get(p.key) or { wr.write_error(jsonrpc.ResponseError{ code: -32004 message: Not found data: p.key }) return } wr.write(KvItem{ key: p.key, value: value }) } fn main() { mut s : KvStore{} mut h : KvHandler{ store: s } mut r : jsonrpc.Router{} r.register(kv.create, h.handle_create) r.register(kv.get, h.handle_get) r.register(kv.update, h.handle_update) r.register(kv.delete, h.handle_delete) r.register(kv.list, h.handle_list) addr : 127.0.0.1:42228 mut l : net.listen_tcp(.ip, addr)! println(TCP JSON-RPC server on ${addr} (Content-Length framing)) for { mut c : l.accept()! println(Accepted) go handle_conn(mut c, r.handle_jsonrpc) } }其中handle_conn与最短路径相同只是额外注册了拦截器见下文“启用日志拦截器”。Handler 内的两条惯例用req.decode_params[T]()解码参数。T是你定义的结构体或基本类型解码失败时按示例返回wr.write_error(jsonrpc.invalid_params)错误码 -32602应用层错误用自定义jsonrpc.ResponseError。示例中“key 已存在”返回code: -32010、“未找到”返回code: -32004并可在data字段带上上下文如 key 名。模块内置的标准错误码定义在 jsonrpc.vparse_error-32700、invalid_request-32600、method_not_found-32601、invalid_params-32602、internal_error-32693等。编写客户端客户端同样只需任意io.ReaderWriter。README 给出的最小用法import net import net.jsonrpc addr : 127.0.0.1:42228 mut stream : net.dial_tcp(addr)! mut c : jsonrpc.new_client(jsonrpc.ClientConfig{ stream: stream }) c.notify(kv.create, { key: bazz value: barr })!完整客户端 examples/jsonrpc/client.v 展示了三种调用方式client.v 源码注释同样说明了各自语义// 1) request发送带 id 的 Request读取并返回 jsonrpc.Response d1 : c.request(kv.delete, { key: foo }, kv.delete)! println(RESULT: ${d1}) // 2) batch批量发送返回 []Response res : c.batch([ jsonrpc.new_request(kv.create, { key: foo value: bar }, kv.create), jsonrpc.new_request(kv.create, { key: bar value: foo }, kv.create), ])! println(RESULT: ${res}) // 3) notifyNotification不带 id发送后不等待 Response c.notify(kv.create, { key: bazz value: barr })!补充请求对象要用构造函数jsonrpc.new_request(method, params, id)初始化id传空字符串即为 Notification编码时不生成id字段request()发送后从流中读取一帧并按 Content-Length 格式解码为jsonrpc.Response解码失败会返回错误服务端对批量请求会自动构造批量 Response客户端的batch()直接返回[]Response。启用日志拦截器可选jsonrpc.Interceptors收集五类事件处理器示例在服务端和客户端都挂载了现成的jsonrpc.LoggingInterceptor按 logging.v 的定义输出[EVENT]、[RAW REQ]、[REQ]、[RESP]、[RAW RESP]格式的消息便于核对线上实际收发的 JSONmut log_inter : jsonrpc.LoggingInterceptor{} mut inters : jsonrpc.Interceptors{ event: [log_inter.on_event] encoded_request: [log_inter.on_encoded_request] request: [log_inter.on_request] response: [log_inter.on_response] encoded_response: [log_inter.on_encoded_response] } mut c : jsonrpc.new_client(jsonrpc.ClientConfig{ stream: stream interceptors: inters })服务端的挂法相同把inters传入jsonrpc.ServerConfig.interceptors。这是可选项不挂载也不影响功能但排查请求内容问题时有用。运行与结果验证在仓库根目录下分别运行v run会构建并直接执行v run examples/jsonrpc/server.v服务端启动后按示例代码打印示例自带输出用于确认监听成功TCP JSON-RPC server on 127.0.0.1:42228 (Content-Length framing)每个客户端接入时再打印一行Accepted。保持该终端运行另开一个终端执行v run examples/jsonrpc/client.v客户端先打印TCP JSON-RPC client on 127.0.0.1:42228随后对每次request()/batch()打印RESULT: ...内容为对应 Response 的 JSON 编码notify则无返回值。挂载了LoggingInterceptor时两端还会输出[REQ]、[RESP]等日志行例如服务端日志中的[REQ] methodkv.create params{key:foo,value:bar} idkv.create说明请求已到达路由。README 中给出的请求编码示例输出文档示例仅说明格式{jsonrpc:2.0,method:kv.create,params:{key:key,value:value},id:kv.create.1}判断是否工作正常的依据客户端能拿到非错误的RESULT输出且服务端打印Accepted及对应的[REQ]/[RESP]日志调用未注册的方法时会收到method_not_found-32601错误响应。限制与排查以下行为均由 README.md 和模块源码明确说明编写自定义 Handler 时需要遵守现象原因与处理连接卡住不返回Handler 返回前没有调用wr.write()/write_error()或两个都调用了。必须且只能调用其一参数结构不匹配时响应错误码 -32602decode_params[T]()解码失败这是invalid_params的正常路径不是传输故障Notification 似乎“没响应”Server 对 Notification 仍会调用 Handler但忽略写入的 Response属于设计行为调用未注册方法返回 -32601Router 对未注册方法自动回method_not_found检查r.register(...)的方法名拼写需要数字 id 或 JSON-RPC 1.0 兼容不支持id仅字符串模块与 JSON-RPC 1.0 不兼容延伸阅读协议结构与编解码细节vlib/net/jsonrpc/jsonrpc.vRequest/Response结构、encode/decode系列函数、标准错误码Server 与 Router 实现vlib/net/jsonrpc/server.vClient 实现vlib/net/jsonrpc/client.v拦截器事件类型vlib/net/jsonrpc/interceptors.v【免费下载链接】vSimple, fast, safe, compiled language for developing maintainable software. Compiles itself in 1s with zero library dependencies. Supports automatic C V translation. https://vlang.io项目地址: https://gitcode.com/GitHub_Trending/v/v创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表