Pythonでpreforkサーバ

Python2.6で試した。
preforkサーバはlistenした後にforkして、それからacceptすればよいみたい?

server.py

import os
import sys
import socket
import signal

child_processes = []

def main(host, port, children):
    signal.signal(signal.SIGTERM, accept_sigterm)

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind((host, port))
    s.listen(1)

    # fork
    for i in range(children):
        pid = os.fork()
        if pid != 0:
            # parent
            sys.stdout.write('child process: pid=%d, getpid=%d\n' % (pid, os.getpid()))
            child_processes.append(pid)
        else:
            # child
            break

    if pid != 0:
        # wait for child
        os.wait()
    else:
        # accept
        while True:
            conn, addr = s.accept()
            data = conn.recv(1024)
            sys.stdout.write('pid=%d data=[%s]\n' % (os.getpid(), data))
            conn.send('pid=%d length=%d OK' % (os.getpid(), len(data)))
        conn.close()

def accept_sigterm(sig, status):
    for pid in child_processes:
        os.kill(pid, signal.SIGTERM)
    sys.exit(0)

if __name__ == '__main__':
    main('127.0.0.1', 5000, 3)

client.py

import sys
import socket

def main(host, port):
    for i in range(10):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((host, port))
        s.send('Hello i=%d' % i)
        data = s.recv(1024)
        s.close()
        sys.stdout.write('received: [%s]\n' % data)

if __name__ == '__main__':
    main('127.0.0.1', 5000)

実行結果

サーバ側

tokibito@vm:~/_sandbox/prefork_socket$ python server.py
child process: pid=29026, getpid=29025
child process: pid=29027, getpid=29025
child process: pid=29028, getpid=29025
pid=29026 data=[Hello i=0]
pid=29027 data=[Hello i=1]
pid=29028 data=[Hello i=2]
pid=29026 data=[Hello i=3]
pid=29027 data=[Hello i=4]
pid=29028 data=[Hello i=5]
pid=29026 data=[Hello i=6]
pid=29027 data=[Hello i=7]
pid=29028 data=[Hello i=8]
pid=29026 data=[Hello i=9]

クライアント側

tokibito@vm:~/_sandbox/prefork_socket$ python client.py
received: [pid=29026 length=9 OK]
received: [pid=29027 length=9 OK]
received: [pid=29028 length=9 OK]
received: [pid=29026 length=9 OK]
received: [pid=29027 length=9 OK]
received: [pid=29028 length=9 OK]
received: [pid=29026 length=9 OK]
received: [pid=29027 length=9 OK]
received: [pid=29028 length=9 OK]
received: [pid=29026 length=9 OK]

signalの使い方がまだよくわかってない。