Python进程间网络远程通讯方式:socket、pipe、RPC详解!

news2024/9/20 0:28:14

背景

最近在进行开发工作的时候,遇到了一个场景:

pc程序需要和安卓设备进行通讯和接口调用。

此时就需要进行远程调用方法。然而大学时代有关于远程过程调用的知识都还给了老师……所以在此进行一个复习,并进行实战演练!

网络远程过程调用

三种方式说明:

  • Socket:主要用于网络通信,它允许不同计算机上的进程通过网络进行数据交换。Socket提供了一个端到端的通信机制,无论是在同一台机器上还是跨网络的不同机器上。
  • Pipe:主要用于同一台机器上的进程间通信(IPC),它实现了一种简单的数据流机制,允许一个进程的输出直接作为另一个进程的输入。Pipe是单向的,数据只能从一个方向流动。
  • RPC:是一种远程过程调用的协议,它允许一个程序通过网络调用另一个地址空间(通常是另一台机器)上的过程(或函数),就像调用本地过程一样。RPC隐藏了网络通信的底层细节,使得远程调用看起来像本地调用一样简单。

相互关系说明:

  • socket和pipe:Socket主要用于跨设备场景,当然也可以用于实现同一台机器上的进程间通信,但是对于同一设备的进程通讯,Pipe更为常见和高效。
  • Socket和RPC:Socket是RPC实现中常用的底层通信机制之一。在RPC框架中,客户端和服务器之间的网络通信通常是通过Socket来完成的。Socket提供了数据传输的通道,而RPC则在这个通道上构建了一个更高层次的调用接口。

方式一:pipe

原理详解:

  • Pipe是一种在Unix和类Unix系统中常用的进程间通信机制。它通过创建一个管道文件来实现数据的单向流动。
  • 当一个进程创建了一个管道时,它会得到两个文件描述符:一个用于写入(写端),另一个用于读取(读端)。写入管道的数据会被存储在内核的缓冲区中,直到被另一个进程读取
  • Pipe的通信是同步的,即写进程在写入数据后会被阻塞,直到读进程读取了数据;同样,读进程在读取数据前也会被阻塞,直到写进程写入了数据

代码示例:

在Windows系统中,Python的multiprocessing模块提供了与Unix系统类似的管道(Pipe)功能,用于进程间通信(IPC)。

from multiprocessing import Process, Pipe  
  
def sender(conn):  
    conn.send("Hello from sender!")  
    conn.close()  
  
def receiver(conn):  
    print("Receiving...")  
    while True:  
        try:  
            data = conn.recv()  
            print(f"Received: {data}")  
        except EOFError:  
            print("No more data. Exiting.")  
            break  
    conn.close()  
  
if __name__ == '__main__':  
    # 创建一个管道  
    parent_conn, child_conn = Pipe()  
  
    # 创建子进程  
    p1 = Process(target=sender, args=(child_conn,))  
    p2 = Process(target=receiver, args=(parent_conn,))  
  
    # 启动子进程  
    p1.start()  
    p2.start()  
  
    # 等待子进程完成  
    p1.join()  
    p2.join()  
  

注意:在Windows上,如果接收者进程在发送者进程之后退出,可能会导致发送者进程中的管道连接在关闭时出现问题。  

方式二:socket

原理详解:

  • Socket是计算机网络编程中的一种抽象,它提供了在网络上进行通信的接口。Socket本质上是一种通信的端点,它在网络上标识了一个通信链路的两端,并提供了通信双方所需的接口和功能。
  • 在TCP/IP协议栈中,Socket位于传输层和应用层之间,它使用传输层提供的服务(如TCP或UDP)来实现网络通信。
  • TCP Socket基于TCP协议,提供可靠的、有序的数据传输服务。它通过三次握手建立连接,确保数据的可靠性和顺序性。
  • UDP Socket基于UDP协议,提供简单的数据传输服务,但不保证数据的可靠性和顺序性。它适用于一些实时性要求高、允许一定数据丢失的应用场景。

代码示例:

服务端:
import socket  
  
def tcp_server(host='127.0.0.1', port=12345):  
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
    server_socket.bind((host, port))  
    server_socket.listen(5)  # 最多可以挂起5个连接  
  
    print(f"Server is listening on {host}:{port}")  
  
    while True:  
        client_socket, addr = server_socket.accept()  
        print(f"Connected by {addr}")  
  
        try:  
            while True:  
                data = client_socket.recv(1024)  
                if not data:  
                    break  
                print(f"Received: {data.decode()}")  
                client_socket.sendall(data)  # Echo back the data  
        finally:  
            client_socket.close()  
  
if __name__ == '__main__':  
    tcp_server()
客户端:
import socket  
  
def tcp_client(host='127.0.0.1', port=12345):  
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
    client_socket.connect((host, port))  
  
    try:  
        while True:  
            message = input("Enter message: ")  
            if message == 'quit':  
                break  
            client_socket.sendall(message.encode())  
            data = client_socket.recv(1024)  
            print(f"Received: {data.decode()}")  
    finally:  
        client_socket.close()  
  
if __name__ == '__main__':  
    tcp_client()

方式三:RPC

原理详解:

  • RPC是一种远程过程调用的协议,它允许程序通过网络调用远程地址空间上的过程。RPC隐藏了网络通信的底层细节,使得远程调用看起来像本地调用一样简单。
  • RPC的实现通常包括客户端和服务器两部分。客户端负责发起远程调用请求,并接收服务器返回的调用结果;服务器则负责接收客户端的请求,执行相应的过程,并将结果返回给客户端。
  • RPC框架通常会在客户端和服务器之间建立一条或多条Socket连接,用于传输远程调用的请求和响应。这些Socket连接可以是持久的(长连接),也可以是临时的(短连接)。
  • RPC框架还需要处理一些额外的任务,如参数和结果的序列化与反序列化、网络异常的处理、服务调用的负载均衡等。这些任务通常是由RPC框架本身来完成的,以减轻应用程序的负担。

 

代码示例:

1. .proto 文件(helloworld.proto

这个文件定义了gRPC服务的接口,使用Protocol Buffers语法。

// 使用proto3语法  
syntax = "proto3";  
  
// 定义包名,防止命名冲突  
package helloworld;  
  
// 定义Greeter服务  
service Greeter {  
  // 定义一个RPC方法SayHello,它接收HelloRequest并返回HelloReply  
  rpc SayHello (HelloRequest) returns (HelloReply) {}  
}  
  
// 定义HelloRequest消息,包含一个string类型的name字段  
message HelloRequest {  
  string name = 1; // 字段编号为1  
}  
  
// 定义HelloReply消息,包含一个string类型的message字段  
message HelloReply {  
  string message = 1; // 字段编号为1  
}
2. Java 服务端实现

这里假设你已经使用protoc编译器和gRPC Java插件生成了GreeterGrpc.javaHelloworld.java等自动生成的代码。

import io.grpc.Server;  
import io.grpc.ServerBuilder;  
import io.grpc.stub.StreamObserver;  
import helloworld.GreeterGrpc;  
import helloworld.GreeterOuterClass;  
  
// 实现GreeterGrpc.GreeterImplBase,提供SayHello方法的具体实现  
public class HelloWorldServer {  
  static class HelloWorldImpl extends GreeterGrpc.GreeterImplBase {  
    @Override  
    public void sayHello(GreeterOuterClass.HelloRequest req, StreamObserver<GreeterOuterClass.HelloReply> responseObserver) {  
      // 构造回复消息  
      GreeterOuterClass.HelloReply reply = GreeterOuterClass.HelloReply.newBuilder()  
          .setMessage("Hello " + req.getName())  
          .build();  
      // 发送回复并标记RPC调用完成  
      responseObserver.onNext(reply);  
      responseObserver.onCompleted();  
    }  
  }  
  
  public static void main(String[] args) throws Exception {  
    // 在指定端口上创建并启动gRPC服务器  
    Server server = ServerBuilder.forPort(50051)  
        .addService(new HelloWorldImpl())  
        .build()  
        .start();  
    System.out.println("Server started, listening on 50051");  
    // 等待服务器终止(通常是通过某种方式发送的关闭信号)  
    server.awaitTermination();  
  }  
}
3. Python 客户端实现

这里假设你已经使用protoc编译器和gRPC Python插件生成了__init__.pyhelloworld_pb2.pyhelloworld_pb2_grpc.py等自动生成的代码。

import grpc  
  
import helloworld_pb2  
import helloworld_pb2_grpc  
  
def run():  
    # 创建一个不安全的通道连接到服务器  
    with grpc.insecure_channel('localhost:50051') as channel:  
        # 创建Greeter服务的存根(stub)  
        stub = helloworld_pb2_grpc.GreeterStub(channel)  
        # 构造请求消息  
        response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'))  
        # 打印响应消息  
        print("Greeter client received: " + response.message)  
  
if __name__ == '__main__':  
    run()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2118813.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

风趣图解LLMs RAG的15种设计模式-第三课

设计模式9-重新排名以优化搜索结果 设计模式10-使用上下文压缩优化搜索结果 设计模式11-使用纠正RAG对检索文档打分和过滤 今天先讲这些吧

java网络编程TCP通信实战:共享聊天室

目录 创建服务端 建立ServerSocket服务端。 接下来就是服务端线程的编写 前端ui登录界面 客户端线程 群聊界面 package server;import java.net.ServerSocket; import java.net.Socket; import java.util.HashMap; import java.util.Map;public class Server {//定义一个集…

DBC中一种特殊的特殊的Signal—多路复用Signal

前言&#xff1a; DBC设计中一般设计Signal时其实存在三种类型&#xff0c;如下图所示&#xff1a; **1&#xff09;步骤1&#xff0c;鼠标单击展开Message&#xff0c;选中底下的Signal **2&#xff09;步骤2&#xff0c;弹出dialog中选择 map signal **3&#xff09;得到…

深入解读Docker核心原理:Cgroups资源限制机制详解

在容器化技术中&#xff0c;除了资源的隔离&#xff0c;如何有效地控制和分配系统资源同样至关重要。Cgroups&#xff08;Control Groups&#xff09; 是Linux内核提供的一个强大机制&#xff0c;允许限制、监控和隔离进程组的系统资源使用情况。Cgroups是Docker实现容器资源限…

用RNN(循环神经网络)预测股票价格

RNN&#xff08;循环神经网络&#xff09;是一种特殊类型的神经网络&#xff0c;它能够处理序列数据&#xff0c;并且具有记忆先前信息的能力。这种网络结构特别适合于处理时间序列数据、文本、语音等具有时间依赖性的问题。RNN的核心特点是它可以捕捉时间序列中的长期依赖关系…

【项目】云备份

云备份 云备份概述框架 功能演示服务端客户端 公共模块文件操作模块目录操作模块 服务端模块功能划分功能细分模块数据管理热点管理 客户端模块功能划分功能细分模块数据管理目录检查文件备份 云备份 概述 自动将本地计算机上指定文件夹中需要备份的文件上传备份到服务器中。…

【网络原理】❤️Tcp 核心机制❤️ 通晓可靠传输的秘密, 保姆式教学, 建议收藏 !!!

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

QT QxOrm CRUD增删改查mysql数据库操作

QT QxOrm CRUD增删改查mysql数据库操作 QxOrm 是一个 C 库&#xff0c;旨在为 C 用户提供对象关系映射 (ORM) 功能。 基于每个类的简单 C 设置函数&#xff08;如 Java 中的 Hibernate XML 映射文件&#xff09;&#xff0c;QxOrm 库提供以下功能&#xff1a; 持久性&#xff1…

安宝特案例 | AR如何大幅提升IC封装厂检测效率?

前言&#xff1a;如何提升IC封装厂检测效率&#xff1f; 在现代电子产品的制造过程中&#xff0c;IC封装作为核心环节&#xff0c;涉及到复杂处理流程和严格质量检测。这是一家专注于IC封装的厂商&#xff0c;负责将来自IC制造商的晶圆进行保护、散热和导通处理。整个制程繁琐…

C语言俄罗斯方块(VS2022版)

C语言俄罗斯方块 演示视频一、前置知识1.Win32 API 的使用2.宽字符的使用 二、封装核心数据与框架介绍三、核心操作介绍旋转操作检测操作水平检测竖直检测代码化简 四、源码展示在 tetris.h 中&#xff1a;在 tetris.c 中&#xff1a;在 test.c 中&#xff1a; 以下代码环境为 …

小阿轩yx-Zabbix企业级分布式监控环境部署

小阿轩yx-Zabbix企业级分布式监控环境部署 前言 “运筹帷幄之中&#xff0c;决胜千里之外”监控在 IT 运维中占据着重要地位&#xff0c;按比例说占 30% 也不为过在监控系统开源软件中有很多可选择的工具&#xff0c;但是真正符合要求的、能够真正解决业务问题的监控系统软件…

W外链微信推广短连接怎么做?

制作微信推广链接的难点分析 一、内容创作难度 制作微信推广链接时&#xff0c;首先需要创作有吸引力的内容。这不仅要求内容本身有趣、有价值&#xff0c;还要能够激起人们的分享欲望。对于许多企业和个人来说&#xff0c;尤其是那些缺乏创意和写作能力的人来说&#xff0c;…

OpenHarmony鸿蒙开发( Beta5.0)智能甲醛检测系统实践

样例简介 本项目是基于BearPi套件开发的智能甲醛检测系统Demo&#xff0c;该设备硬件部分主要由小熊派单板套件和和甲醛检测传感器组成。智能甲醛检测系统可以通过云和手机建立连接&#xff0c;可以在手机上设置甲醛浓度阈值&#xff0c;传感器感知到的甲醛浓度超过阈值之后&a…

QQ邮箱“已发送”邮件竟然无法一键清空?看我操作,怎么删除12万+已发送邮件

最近遇到了一个问题&#xff0c;QQ邮箱提示我空间已满&#xff0c;所以我就专门去看看有哪些邮件可以删除&#xff0c;释放点空间。 我直接暴力删除了很多文件夹的邮件&#xff0c;在文件夹管理界面 有“清空”按钮&#xff0c;点一个即可清空。 但是。。。不出意外的话要出意…

南卡、韶音、墨觉:精选三款旗舰骨传导耳机全面对比评测!

在科技日新月异的今天&#xff0c;耳机作为我们日常生活中不可或缺的音频伴侣&#xff0c;正经历着前所未有的变革。特别是骨传导耳机&#xff0c;凭借其独特的声音传导方式和出色的佩戴体验&#xff0c;逐渐成为了运动爱好者和户外探索者的首选。在众多品牌中&#xff0c;南卡…

Pycharm的安装与Conda环境的配置

目录 第一步&#xff1a;下载并安装 PyCharm 社区版 第二步&#xff1a;创建新项目并配置 Python 解释器 第三步&#xff1a;配置 Conda 环境 第四步&#xff1a;验证环境 第五步&#xff1a;测试 PyTorch 第六步&#xff1a;测试基本 PyTorch 代码 第一步&#xff1a;下…

替代区块链

随着比特币的成功&#xff0c;人们逐渐意识到区块链技术的潜力&#xff0c;并随之出现了迅速的发展&#xff0c;各种区块链协议、应用程序和平台相应产生。 需要指出的是&#xff0c;在这种多元的局面下&#xff0c;很多项目迅速失去了它们的吸引力。事实上&#xff0c;有不少项…

深圳MES系统在制造业的应用与发展

深圳MES在制造业的应用与发展呈现以下几个特点&#xff1a; 应用范围广泛&#xff1a;深圳制造业涵盖了电子、通信、汽车、机械等多个领域&#xff0c;MES系统在这些领域的应用非常广泛。不同行业的企业可以根据自身的需求和特点&#xff0c;定制化地应用MES系统来实现生产管理…

测试即服务(TaaS):概念、优势及应用场景!

引言 随着数字化转型的深入发展&#xff0c;软件质量和用户体验变得愈发重要。传统的软件测试方法已经难以满足现代企业对于快速迭代和高质量交付的需求。在此背景下&#xff0c;“测试即服务”(Testing as a Service, TaaS) 模式应运而生&#xff0c;为软件测试带来了新的解决…

基于SpringBoot+Vue+MySQL的足球俱乐部管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统足球俱乐部管理…