用Python操作Named pipe命名管道,实用做法

        在我以前做过的用于手游服务器的Python服务器框架里,我用了Python的multiprocessing库,多进程通信用了multiprocessing提供的最方便的queue,实际上就是一种匿名管道。要求管道两端的进程必须是父子进程或者兄弟进程。

        匿名管道给后续扩展带来影响,无法动态的增加或者减少服务进程。如果可以动态增加减少进程,至少在非严重故障时重启服务器会方便很多。


       之前研究了一阵命名管道,遇到很多问题。这两天有空再次试验,想明白了很多。直接看例子。


客户端  Client.py:

# named pipe Client
#encoding: utf-8

import os
import time

write_path = "/tmp/server_in.pipe"
read_path = "/tmp/server_out.pipe"

counter = 1

f = os.open( write_path, os.O_SYNC | os.O_CREAT | os.O_RDWR )
print "Client open f", f

rf = None

while True:
    # Client发送请求
    req = "%s "%counter 
    len_send = os.write( f, req )
    print "request", req, len_send

    counter += 1
    
    if rf == None:
        # *要点1:在这里第一次打开read_path,实际这里的open是一个阻塞操作
        # 打开的时机很重要。如果在程序刚开始,没发送请求就打开read_path,肯定会阻塞住
        rf = os.open( read_path, os.O_RDONLY )
        print "client opened rf", rf

    # 接收Server回应
    s = os.read( rf, 1024 )
    if len(s) == 0:
        # 一般来说,是管道被意外关闭了,比如Server退出了
        break

    print "received", s

    # 这个例子里没有sleep,客户端以最高速度发送数据,可以观察执行效果


os.close( f )
os.close( rf )

服务器  Server.py:

#named pipe Server
#encoding: utf-8

import os, time

read_path = "/tmp/server_in.pipe"
write_path = "/tmp/server_out.pipe"

try:
    # 创建命名管道
    os.mkfifo( write_path )
    os.mkfifo( read_path )
except OSError, e:
    # 如果命名管道已经创建过了,那么无所谓
    print "mkfifo error:", e

# 写入和读取的文件,正好和Client相反
rf = os.open( read_path, os.O_RDONLY )
f = os.open( write_path, os.O_SYNC | os.O_CREAT | os.O_RDWR )

while True:
    # 接收请求
    s = os.read( rf, 2 )
    if len(s) == 0:
        # 没有收到字符,一般是唯一的发送方被关闭了。
        # 这里可以休息一下继续,对后续消息没有任何影响,也不会丢包。
        time.sleep( 1 )
        continue

    # 如果收到的字符串带一个s,打印出来
    # 用于调试和测试
    if "z" in s:
        print "received", s

    # 在请求前面加一个s字母,返回
    os.write( f, "s%s"%s )

os.close( f )
os.close( rf )


        这个例子具有一定实用性:

        1、无论先执行Server.py还是Client.py都可以正常工作。

        2、Server.py与Client.py执行时,可以在另一个控制台里输入   echo zzzzz > /tmp/server_in.pipe,可以观察到,server可以同时处理多个来源的请求

        3、实际上在进程交互时,每个进程既是一个Client又是一个Server,每个进程只有一个用于接收别人请求的pipe,然后接收请求后把处理结果返回给发送方的pipe。这样网络就联系起来了。和匿名管道的架构是一致的。

你可能感兴趣的:(编程,python)