首页天道酬勤python rabbitmq,socketio python

python rabbitmq,socketio python

张世龙 05-13 12:08 98次浏览

效果通过socket实现RPC,能够从客户端调用服务端的函数并返回结果

另一方面,套接字的基础是在构建自己的RPC之前,首先需要了解Socket的一些用法和RPC是什么。 以下分三个方框来说。 分别是1、什么是socket 2、socket模块 3、套接字对象内建方法 4、什么是PRC

1.什么是socket

套接字是一组接口,APP应用层是与TCP/IP协议系列进行通信的中间软件抽象层。 在设计模式下,套接字实际上是门模式,将复杂的TCP/IP协议族隐藏在套接字接口之后,用户可以看到所有简单的接口集,并且套接字与指定的协议相匹配

因此,不需要深入理解tcp/udp协议。 套接字已经封装,只要按照套接字的规定进行编程,编写的程序当然就符合tcp/udp标准。2.socket模块

要使用socket.socket ()函数创建套接字,请执行以下操作: 语法如下:

socket.socket(socket_family,socket_type,协议=0) )。

socket_family可以是以下参数:

socket.AF_INET IPv4 ((默认) ) ) ) ) ) ) )。

socket.AF_INET6 IPv6

socket.AF_Unix只能用于单个UNIX系统进程间通信

socket_type可以是以下参数:

socket.SOCK_STREAM流媒体socket,for TCP (默认)

socket.SOCK_DGRAM数据报表达式socket,for UDP

socket.SOCK_RAW原始套接字、普通套接字无法处理ICMP、IGMP等网络消息,而SOCK_RAW; 接着,SOCK_RAW还可以处理特殊的IPv4消息; 此外,原始套接字允许用户使用IP_HDRINCL套接字选项构建IP标头。

socket.SOCK_RDM是一种可靠的UDP格式,可以保证数据报的分发,但不保证其顺序。 SOCK_RAM用于提供对原始协议的低级访问,并在需要执行某些操作(如发送ICMP消息)时使用。 SOCK_RAM通常仅用于高级用户或管理员运行的程序。

socket.sock _ seq包可信连续包服务

协议参数:

0 )默认)特定地址系列的协议,如果为0,则根据地址格式和套接字类别自动选择相应的协议

3.套接字对象内建方法

服务器端套接字函数

s .绑定s.bind (是套接字的地址) ip地址、端口。 参数必须是元组格式。 例如: s.bind ) ) ).0.1 )、8009 ) )

s.Listen(5)开始监听,5是最大保留连接数

s.accept ) )被动接受、阻止客户端连接并等待连接

客户端套接字函数

s.connect ()必须连接到服务器端,参数必须是元组格式。 示例: s.connect ) )、0.0.1 )和8009 ) )

通用用途的套接字函数

s.recv(1024 )接收TCP数据,其中1024是一次数据接收的大小

s.send(bytes )发送TCP数据,python3发送数据的格式必须是bytes格式

s.sendall ()完全发送数据,内部循环调用send

s.close ) )关闭插座

4.什么是RPC

远程过程调用协议RPC----可以像调用本地服务一样调用远程服务。

二、代码实现#服务端RPC server.py #-*-coding : utf-8-*-importjsonimportsocketfuns={ } def register _ function ) ) ) 在客户端,注册的方法' ' name=func._ name _ funs [ name ]=funcclasstcpserver (object ) 3360 def _ _ init _ (3365365306; socket.SOCK_STREAM ) self.client _ socket=nonedefbind _ ) none port ) :self.sock.bind(0.0.0',port )

取Client端信息""" if self.client_socket is None: (self.client_socket, address) = self.sock.accept() if self.client_socket: msg = self.client_socket.recv(1024) data = self.on_msg(msg) self.client_socket.send(data) # 回传class RPCStub(object): def __init__(self): self.data = None def call_method(self, data): """解析数据,调用对应的方法变将该方法执行结果返回""" if len(data) == 0: return json.dumps("something wrong").encode('utf-8') self.data = json.loads(data.decode('utf-8')) method_name = self.data['method_name'] method_args = self.data['method_args'] method_kwargs = self.data['method_kwargs'] res = funs[method_name](*method_args, **method_kwargs) data = res return json.dumps(data).encode('utf-8')class RPCServer(TCPServer, RPCStub): def __init__(self): TCPServer.__init__(self) RPCStub.__init__(self) def loop(self, port): # 循环监听 5003 端口 self.bind_listen(port) print('Server listen 5003 ...') while True: try: self.accept_receive_close() except Exception: self.client_socket.close() self.client_socket = None continue def on_msg(self, data): return self.call_method(data)@register_functiondef add(a, b, c=10): sum = a + b + c print(sum) return sum@register_functiondef setData(data): print(data) return datas = RPCServer()s.loop(5003) # 传入要监听的端口 # 客户端 RpcClient.py# -*- coding: utf-8 -*-import jsonimport socketclass TCPClient(object): def __init__(self): self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) def connect(self, host, port): """链接Server端""" self.sock.connect((host, port)) def send(self, data): """将数据发送到Server端""" self.sock.send(data) def recv(self, length): """接受Server端回传的数据""" return self.sock.recv(length)class RPCStub(object): def __getattr__(self, function): def _func(*args, **kwargs): d = {'method_name': function, 'method_args': args, 'method_kwargs': kwargs} self.send(json.dumps(d).encode('utf-8')) # 发送数据 data = self.recv(1024) # 接收方法执行后返回的结果 return data.decode('utf-8') setattr(self, function, _func) return _funcclass RPCClient(TCPClient, RPCStub): passc = RPCClient()c.connect('127.0.0.1', 5003)print(c.add(1, 2, 3))print(c.setData({"sss": "ssss", "list": [1, 2, 3, 4]}))

服务端:
1、服务端对“本机的5003”端口进行监听
2、对服务端的方法进行注册“register_function”
3、对客户端传送过来的数据进行解析,查询对应的函数并将参数传入,返回给客户端
客户端:
1、客户端对服务端进行连接
2、将调用的方法名、参数传入服务端,服务端将数据进行返回
两者之间的数据采用Json文本格式

三、运行结果

服务端结果:

客户端结果:

此时我们如果再运行一次客户端

服务端结果:

客户端结果:

四、注意点

如果连接断开了(这里指客户端断开连接,如果服务端断开了,那只能重启了),需要重新创建套接字socket,重新连接
整个RPC的流程: 创建socket->建立连接->进行消息交互->关闭socket

五、后续扩充

1、在 S-C之间保持连接的时候,为了防止意外断连,可以采用心跳包的形式,每隔一段时间进行一次心跳包同步,如果断连了就重新进行socket连接
2、服务端可以将socket扩充为list,并利用address进行区分,实现多个客户端连接

六、参考文章

本文是参考下面文章整合并对代码加以改进写的
socket基础
RPC原文参考
参考二

rpc底层原理,rpc协议详解 如何知道使用了ucos系统,嵌入系统