您好,欢迎访问一九零五行业门户网

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

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
协议请求定义:
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下载,到底什么区别呢?
以上就是如何在远程过程调用(rpc)的详细内容。
其它类似信息

推荐信息