讲师中心 微信公众号
AI工具推荐 视频效率加速

如何在远程过程调用(RPC)

云杰吖_9741

云杰吖_9741

发布时间:2018-09-14 11:44:18

|

4822人浏览过

|

来源于php中文网

原创

http请求式 做过socket编程的人都知道,当我们设计一个通信协议时,“消息头/消息体”的分割方式是很常用的,消息头告诉对方这个消息是干什么的,消息体告诉对方怎么干。

基于HTTP协议实现RPC和基于TCP协议实现RPC比较:

       基于HTTP协议的系统间的 RPC,具有灵活、实现便捷(多种开源的web服务器支持)、开放(国际标准)且天生支持异构平台之间的调用等多个优点,得到了广泛的使用。与之相对应的是TCP协议的实现版本,它效率更高,但实现起来更加复杂,且由于协议和标准的不同,难以进行跨平台和企业间的便捷通信。

       HTTP协议实现有其劣势的一面,由于是上层协议,发送包含同等内容的信息,使用HTTP协议传输所占用的字节数肯定要比使用TCP协议传输所占用的字节数更多。因此,同等网络环境下,通过HTTP协议传输相同内容,效率会比TCP协议的数据传输要低,信息传输所占用的时间更长。当然,通过优化代码实现和使用gzip数据压缩,能够缩小这一差距。通过权衡利弊,结合实际环境中其性能对于用户体验的影响来看,基于HTTP协议的RPC还是有很大优势的。

1.基于TCP协议实现RPC

服务接口:

public interface SayHelloService{
     public String sayHello(String helloArg);
}

服务实现:

public class SayHelloServiceImpl implements SayHelloService {
    
    @Override
    public String sayHello(String helloArg) {
        if(helloArg.equals("Hello")) {
            return "hello";
        }else{
            return "bye bye";
        }
    }          
}

服务消费者Consumer关键代码:

// 接口名称
String interfacename = SayHelloService.class.getName();
// 需要远程执行的方法
Method method = SayHelloService.class.getMethod("sayHello", java.lang.String.class);
// 需要传递到远端的参数
Object[] arguments = {"hello"};
Socket socket = new Socket("127.0.0.1", 1234);
// 将方法名称和参数传递到远端
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
output.writeUTF(interfacename); // 接口名称
output.writeUTF(method.getName()); // 方法名称
output.writeObject(method.getParameterTypes());
output.writeObject(arguments);

// 从远端读取方法的执行结果
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
Object result = input.readObject();

服务提供者Privider关键代码:

ServiceSocket server = new ServerSocket(1234);
while(true){
    Socket socket = server.accept();

    //读取服务信息
    ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
    String interfacename = input.readUTF();    //接口名称
    String methodName = input.readUTF();    // 方法名称
    Class<?>[] parameterTypes = (Class<?>[])input.readObject(); //参数类型
    Object[] arguments = (Object[]) input.readObject(); //参数对象
    
    // 执行调用
    Class serviceinterfaceclass = Class.forName(interfacename);
    Object service = service.get(interfacename);
    Method method = serviceinterfaceclass.getMethod(methodName, parameterTypes);
    Object result = method.invoke(service, arguments);

    ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
    output.writeObject(result);
}

2. 基于HTTP协议的RPC

PHP
PHP

编写健壮的PHP代码,规避类型转换陷阱、数组怪癖及常见安全漏洞。

下载

协议请求定义:

public class Request{
    
    /**
    * 协议编码
    */
    private byte encode;

    /**
    * 命令
    */
    private String command;

    /**
    * 命令长度
    */
    private int commandLength;
}

协议响应的定义:

public class Response {

    /**
    * 编码
    */
    private byte encode;

    /**
    * 响应长度
    */
    private int responseLength;

    /**
    * 响应
    */
    private String response;
}

客户端实现关键代码:

// 请求
Request request = new Request();
request.setCommand("HELLO");
request.setCommandLength(request.getCommand().length());
request.setEncode(Encode.UTF8.getValue());

Socket client = new Socket("127.0.0.1", 4567);
OutputStream output = client.getOutputStream();

// 发送请求
ProtocolUtil.writeRequest(output, request);
InputStream input = client.getInputStream();
Response = response = ProtocolUtil.readResponse(input);

服务端实现关键代码:

ServerSocket server = new ServerSocket(4567);
while(true){
    Socket client  = server.accept();
   
    //读取响应数据
    InputStream input = client.getInputStream();
    Request request = ProtocolUtil.readRequest(input);
    OutputStream output = client.getOutputStream();
    
    // 组装响应
    Response response = new Response();
    response.setEncode(Encode.UTF8.getValue());
    if(request.getCommand().equals("HELLO")){
       response.setResponse("hello!"); 
    }else {
        response.setResponse("bye bye");    
    }
    
    resposne.setResponseLength(response.getResponse().length());
    ProtocolUtil.writeResponse(output, response);
}

ProtocolUtil 代码

public class ProtocolUtil {

    public static Request readRequest(InputStream input) throws IOException {
        //读取编码
        byte[] encodeByte = new byte[1];
        input.read(encodeByte);
        byte encode = encodeByte[0];
        
        //读取命令长度
        byte[] commandLengthBytes = new byte[4];
        input.read(commandLengthBytes);
        int commandLength = ByteUtil.bytes2Int(commandLengthBytes);

        //读取命令
        byte[] commandBytes = new byte[commandLength];
        input.read(commandBytes);
        String command = "";
        if(Encode.GBK.getValue() == encode){
            command = new String(commandBytes, "GBK");
        }else{
            command = new String(commandBytes, "UTF8");
        }

        // 组装请求返回
        Request request = new Request();
        request.setCommand(command);
        request.setEncode(encode);
        request.setCommandLength(commandLength);

        return request;
    }

    public static void writeResponse(OutputStream output, Response response) throws IOExceptiono{
        //将response响应返回给客户端
        output.write(response.getEncode());
       // output.write(response.getResponseLength()); 
        //直接write一个int类型会截取低8位传输,丢失高8位
        output.write(ByteUtil.int2ByteArray(response.getResponseLength()));
        if(Encode.GBK.getValue() == resposne.getEncode()){
            output.write(response.getResponse().getBytes("GBK"));
        }else{
            output.write(response.getResponse().getBytes("UTF8"));
        }

        output.flush();
    }
}
public static int bytes2Int(byte[] bytes){
    int num = bytes[3] & 0xFF;
    num |= ((bytes[2] << 8) & 0xFF00;
    num |= ((bytes[1] << 16) & 0xFF0000;
    num |= ((bytes[0] << 24) & oxFF000000;

    return num;
}

 相关推荐:

HTTP初步注解 - Yitoem

http://windows.php.net/ 和 http://php.net/ 都提供PHP下载,到底什么区别呢?

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

相关专题

更多
AionClaw AI智能体与电脑自动化任务执行功能使用教程
AionClaw AI智能体与电脑自动化任务执行功能使用教程

AionClaw专题整理AI智能体与电脑自动化相关功能使用教程,涵盖安装部署、AI任务执行、Skills技能、文件处理、浏览器控制、电脑操作、持久记忆、聊天工具连接以及办公、编程和内容创作等功能,帮助用户快速掌握AionClaw的实际使用方法。

0

2026.09.20

AI视频生成软件推荐
AI视频生成软件推荐

本专题汇总了当前主流的AI视频生成软件推荐与排行榜单,涵盖seko、AniShort、剧云、Lovart、LiblibAI及立刻mv等热门工具。同时整理了各软件在文生视频、图生视频、时长限制、画质表现及免费额度等方面的差异对比,助您快速选对适合创作需求的AI视频生成工具。

160

2026.09.16

ai生成视频的工具免费版合集
ai生成视频的工具免费版合集

本专题汇总了当前免费AI生成视频工具的排行榜与推荐清单,涵盖seko、讯飞智作、AniShort及剧云、Lovart等多模型集成平台。同时整理了各工具的免费额度、输出时长、水印政策及适用场景差异,助您快速选择合适工具开启AI视频创作。

60

2026.09.16

Pandas时间序列分析与可视化报表
Pandas时间序列分析与可视化报表

本专题整理Pandas日期转换、时间索引、重采样、滚动窗口、时区处理、plot绘图、Styler表格样式和报表输出方法。

80

2026.09.16

Pandas数据筛选索引与清洗处理
Pandas数据筛选索引与清洗处理

本专题整理Pandas中的loc、iloc、条件筛选、query查询、缺失值处理、重复值删除、类型转换和字符串列清洗方法。

60

2026.09.16

Pandas数据读取导入与文件导出处理
Pandas数据读取导入与文件导出处理

本专题整理Pandas读取CSV、Excel、JSON、SQL、Parquet等文件的方法,以及to_csv、to_excel、to_sql和to_parquet等常用数据导出流程。

40

2026.09.16

GDB怎么设置断点
GDB怎么设置断点

本专题介绍GDB按照函数名、源代码行号和文件位置设置断点的方法,详细说明run、continue、next、step等命令的配合使用,帮助定位程序崩溃、逻辑异常及代码未按预期执行的问题。

380

2026.09.11

GDB怎么查看变量值
GDB怎么查看变量值

本专题介绍GDB调试过程中查看变量值的具体方法,涵盖局部变量、函数参数、数组、结构体和指针内容查询,同时整理变量持续显示、格式化输出及无法读取变量时的排查思路。

120

2026.09.11

GDB C++程序怎么调试
GDB C++程序怎么调试

本专题围绕GDB调试C++程序的实际过程,详细说明程序编译、调试器启动、命令行参数传入、断点命中和程序继续运行等步骤,并介绍条件断点、临时断点和观察点的设置方法,方便开发者跟踪复杂代码的执行状态。

140

2026.09.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Webman中文手册
Webman中文手册

共0课时 | 0人学习

Swoole手册
Swoole手册

共0课时 | 0人学习

【web前端】Node.js快速入门
【web前端】Node.js快速入门

共16课时 | 2.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn