进程间通信(IPC)方式
目录
Socket
管道
匿名管道
消息队列
共享内存
信号
远程过程调用
Socket
Socket编程是一种在计算机网络中进程间通信的编程方法。Socket提供了一种在不同主机上运行的进程之间传输数据的机制。通过使用Socket API,开发者可编写用于发送和接收数据的客户端和服务器应用程序。
Scope:Socket通常用于实现C-S架构的网络应用程序,如Web服务器、聊天应用程序等
以下是一Python Socket编程示例,包括一个TCP回显服务器和一个TCP客户端。
客户端:
import socket
def main():
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 12345))
while True:
message = input("Enter message to send (or 'exit' to quit): ")
if message == 'exit':
break
client_socket.sendall(message.encode())
response = client_socket.recv(1024)
print(f"Received: {response.decode()}")
client_socket.close()
if __name__ == "__main__":
main()
# 客户端连接到本地主机的端口12345上的服务器。
# 客户端从用户输入获取消息,将其发送到服务器,并接收服务器的回显响应。
# 当用户输入“exit”时,客户端断开连接并退出。
服务器:
import socket
def main():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 12345))
server_socket.listen(5)
print("Server is listening on port 12345...")
while True:
client_socket, client_address = server_socket.accept()
print(f"Connection from {client_address}")
data = client_socket.recv(1024)
while data:
print(f"Received: {data.decode()}")
client_socket.sendall(data)
data = client_socket.recv(1024)
print("Closing connection")
client_socket.close()
if __name__ == "__main__":
main()
# 服务器在本地主机的端口12345上监听连接。
# 当客户端连接到服务器时,服务器会接收客户端发送的数据,并将其回显(发送)回客户端。
# 当客户端断开连接时,服务器关闭与客户端的连接并继续监听新的连接。
管道
管道(Pipe):管道是一种基于字节流的通信方式,通常用于具有父子关系的进程之间的通信。
scope:管道通常用于实现命令行程序的输入输出重定向和管道操作。
以下示例用python实现,用os.pipe()
在父子进程之间进行通信。
import os
def main():
r, w = os.pipe()
if os.fork():
# 父进程
os.close(w)
r = os.fdopen(r)
print("Parent: Received message:", r.read())
r.close()
else:
# 子进程
os.close(r)
w = os.fdopen(w, 'w')
w.write("Hello from child process!")
w.close()
if __name__ == "__main__":
main()
更常用的,Linux中的命令比如
# cat命令读取名为input.txt文件内容,并传递给grep命令过滤包含信息的行,过滤结果保存到名为output.txt的文件中。
cat input.txt | grep 'pattern' > output.txt
示例中涉及到三个进程:
-
cat
命令:这个进程负责读取input.txt
文件的内容。cat
命令将文件内容输出到标准输出(stdout)。 -
grep
命令:这个进程负责从标准输入(stdin)读取数据(即cat
命令的输出),并过滤出包含特定模式的行。grep
命令将过滤后的结果输出到标准输出。 -
输出重定向(
>
):这个操作将grep
命令的输出重定向到output.txt
文件中,而不是显示在屏幕上。
匿名管道
匿名管道(Anonymous Pipe):匿名管道是一种基于文件描述符的通信方式,通常用于具有父子关系的进程之间的通信。
Scope:匿名管道通常用于实现多进程并行计算和数据处理任务。
Python示例,展示了如何使用multiprocessing.Pipe()
在父子进程之间进行通信:
from multiprocessing import Process, Pipe
def child(conn):
conn.send("Hello from child process!")
conn.close()
def main():
parent_conn, child_conn = Pipe()
p = Process(target=child, args=(child_conn,))
p.start()
print("Parent: Received message:", parent_conn.recv())
p.join()
if __name__ == "__main__":
main()
消息队列
消息队列(Message Queue):消息队列是一种基于消息的通信方式,可以用于任意关系的进程之间的通信。比如提供了更高级功能和特性的:RabbitMQ 和 Celery等等。
Scope:消息队列通常用于实现分布式系统和微服务架构中的异步通信和任务分发。
以下示例展示了如何使用multiprocessing.Queue()
在两个进程之间进行通信:
from multiprocessing import Process, Queue
def producer(queue):
queue.put("Hello from producer process!")
def consumer(queue):
print("Consumer: Received message:", queue.get())
def main():
queue = Queue()
p1 = Process(target=producer, args=(queue,))
p2 = Process(target=consumer, args=(queue,))
p1.start()
p2.start()
p1.join()
p2.join()
if __name__ == "__main__":
main()
共享内存
共享内存(Shared Memory):共享内存是一种基于内存的通信方式,可以用于任意关系的进程之间的通信。共享内存允许多个进程访问同一块内存区域,从而实现进程间的数据共享。
Scope:共享内存通常用于实现高性能计算和实时系统中的数据交换和同步。
以下示例展示了如何使用multiprocessing.Value()
在两个进程之间共享内存
from multiprocessing import Process, Value
def increment(shared_value):
shared_value.value += 1
def main():
shared_value = Value('i', 0)
print("Initial value:", shared_value.value)
p = Process(target=increment, args=(shared_value,))
p.start()
p.join()
print("Final value:", shared_value.value)
if __name__ == "__main__":
main()
信号
信号(Signal):信号是一种基于事件的通信方式,用于通知进程有关特定事件(如实现进程管理(如启动、停止、重启等)、错误处理(如段错误、浮点异常等)和状态通知(如子进程终止、终端关闭等)等功能。
Scope:信号通常用于实现进程管理、错误处理和状态通知等功能。
以下Python示例展示了如何使用signal
模块处理信号
import os
import signal
import time
def signal_handler(signum, frame):
print(f"Received signal {signum} at {time.time()}")
def main():
# 注册信号处理函数
signal.signal(signal.SIGUSR1, signal_handler)
# 获取当前进程ID
pid = os.getpid()
print(f"Process ID: {pid}")
# 循环等待信号
while True:
print("Waiting for signal...")
time.sleep(10)
if __name__ == "__main__":
main()
远程过程调用
远程过程调用(Remote Procedure Call,RPC):RPC是一种允许在远程计算机上执行函数或方法的通信方式。RPC隐藏了底层通信细节,使得调用远程函数就像调用本地函数一样简单。以下Python示例展示了如何使用xmlrpc
库实现一个简单的RPC服务器和客户端:
服务器:
from xmlrpc.server import SimpleXMLRPCServer
def add(x, y):
return x + y
def main():
server = SimpleXMLRPCServer(('localhost', 12345)) # 监听本地主机的端口12345
server.register_function(add, 'add') # 服务器注册了一个名为add的函数,用于将两个数相加
print("RPC server is listening on port 12345...")
server.serve_forever()
if __name__ == "__main__":
main()
客户端:
import xmlrpc.client
def main():
proxy = xmlrpc.client.ServerProxy('http://localhost:12345') # 连接到RPC服务器
result = proxy.add(1, 2) # 客户端使用ServerProxy对象调用远程的add函数,并接收返回结果
print("Result:", result)
if __name__ == "__main__":
main()
Scope:RPC通常用于实现分布式系统和微服务架构中的远程服务调用和数据交换。