rpc 的使用

本文介绍了一种基于Python实现的远程过程调用(RPC)机制,通过客户端和服务端的交互展示了如何在网络环境中调用远程方法,包括数据包的构建、解析及通信流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

rpc 的使用
rpc就是将本地的方法放到了服务器端,使得网络通信如同调用方法般简单。
import RemoteCallMethod_pb2
import functools
import ProtobufHelper
from socket import AF_INET,SOCK_STREAM,socket

class RemoteCallClient:    
    buffsize=1024
    def __init__(self,host,port):
        self.host = host
        self.port = port
        ADDR=(HOST , PORT)
        self.client = socket(AF_INET,SOCK_STREAM)
        self.client.connect(ADDR)
    
    def __getattr__(self,method_name):
        return functools.partial(self.execute,method_name)
    
    def execute(self,method_name,*args,**kwargs):
        helper = ProtobufHelper.ProtobufHelper()
        remoteMethodCall = RemoteCallMethod_pb2.RemoteCallMethod()
        remoteMethodCall.methodName = method_name         
        
        remoteMethodCall.methodArgs = helper.parseToProtobuf(args)
        remoteMethodCall.methodKwargs = helper.parseToProtobuf(kwargs)
        strData = remoteMethodCall.SerializeToString()
        self.client.send(strData)   
        
         
        data = self.client.recv(self.buffsize)
        remoteCallRespon = RemoteCallMethod_pb2.RemoteCallRespon()
        remoteCallRespon.ParseFromString(data)                
        return remoteCallRespon.methodRespon
        



HOST='127.0.0.1'
PORT=5000

remoteCallClient = RemoteCallClient(HOST,PORT)
print remoteCallClient.add(3,4)
#print remoteCallClient.sub(3,4)
服务端代码
'''
Created on 2015-1-12

@author: Administrator
'''
from gevent.server import StreamServer
from tool import RemoteCallMethod_pb2
from tool import ProtobufHelper

class RemoteCallSever:
    buffsize=1024
    def __init__(self,host,port):
        self.server = StreamServer((host,port),self.handle)
        self.server.serve_forever()

    
    def handle(self,socket,address):        
        data = socket.recv(self.buffsize)        
        remoteMethodCall = RemoteCallMethod_pb2.RemoteCallMethod()
        remoteMethodCall.ParseFromString(data)
        
        helper = ProtobufHelper.ProtobufHelper()
        methodName = remoteMethodCall.methodName
        args = helper.parseFromProtobuf(remoteMethodCall.methodArgs)
        kwargs = helper.parseFromProtobuf(remoteMethodCall.methodKwargs)
        
        method = getattr(self,methodName,None)
        
        remoteCallRespon = RemoteCallMethod_pb2.RemoteCallRespon()
        if not callable(method):
            remoteCallRespon.methodRespon = 'no this method'
        else :
            remoteCallRespon.methodRespon = str(method(*args,**kwargs))
        
        strData = remoteCallRespon.SerializeToString()
        socket.send(strData)    

    def add(self,a,b):
        return a+b
    
        
    
HOST='127.0.0.1'
PORT=5000
print "\r" 
remoteCallServer = RemoteCallSever(HOST,PORT)
protobuf帮助类
'''
Created on 2015-1-13

@author: Administrator
'''
class ProtobufHelper:  
    def __init__(self):
        pass 
   
    def parseFromDict(self,values,type):
        typestr = type + ':'
        dictStr = ''
        for value in values:
            if len(dictStr) % 2 == 1:
                dictStr += ':'
            elif len(dictStr) > 0 and len(dictStr) % 2 == 0:
                dictStr += ';'
            dictStr += str(value) 
        return typestr+dictStr
    
    
    def parseFromTuple(self,values,type):
        typestr = type + ':'
        tupleStr = ''        
        for value in values:
            if len(tupleStr) > 0:
                tupleStr += ','
            tupleStr += str(value)
        return typestr+tupleStr
    
   
    def parseToProtobuf(self,values):
        if isinstance(values,dict):
            return self.parseFromDict(values,'dict')
        elif isinstance(values,tuple):
            return self.parseFromTuple(values,'tuple')
        elif isinstance(values,list):
            return self.parseFromTuple(values,'list')
    
    def parseToDict(self,values):
        value = '{' + values + '}' 
        return eval(value)
    
    
    def parseToTuple(self,values):
        value = '(' + values + ')'        
        return eval(value)
    
    def parseToList(self,values):
        value = '[' + values + ']' 
        return eval(value)
        
    def parseFromProtobuf(self,values):
        npos = values.find(':')
        type = values[:npos]
        substr = values[npos+1:]        
        if type == 'tuple' :
            return self.parseToTuple(substr)
        elif type == 'dict' :
            return self.parseToDict(substr)
        elif type == 'list' :
            return self.parseToList(substr)
            
        
协议
package rpcMessage;

message RemoteCallMethod {
	required string methodName = 1;
	required string methodArgs = 2;
	required string methodKwargs = 3;
}

message RemoteCallRespon
{
	required string methodRespon = 1;
}

要注意的几点:
1、当类中无此方法时会进入到__getattr__
2、此时构建数据包进行通信,等待应答
3、远程收到消息后通过method = getattr(self,methodName,None),判断类中有无方法
4、进行应答响应
5、原等待return.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值