Python で UNIX domain socket 経由で fd を受け渡す
プロセス間で fd を受け渡すには fork で引き継ぐ のが一般的だけど、 UNIX domain socket を通じて受け渡すことも可能らしいので、 python でやってみた。
コード
send_fd.py
:
import array import socket input_file = open('spam.txt', 'rb', buffering=0) fd = input_file.fileno() print('send_fd:', input_file.read(5)) sock = socket.socket(socket.AF_UNIX) sock.bind('/tmp/send_fd.sock') sock.listen(1) conn, addr = sock.accept() # 送る conn.sendmsg([b'\x00'], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, array.array('i', [fd]))]) conn.close() sock.close() input_file.close() print('end')
recv_fd.py
:
import array import os import socket sock = socket.socket(socket.AF_UNIX) sock.connect('/tmp/send_fd.sock') # 受け取る fds = array.array('i') msg, ancdata, flags, addr = sock.recvmsg(1, socket.CMSG_LEN(fds.itemsize)) for cmsg_level, cmsg_type, cmsg_data in ancdata: if (cmsg_level == socket.SOL_SOCKET and cmsg_type == socket.SCM_RIGHTS): fds.fromstring(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) fd = list(fds)[0] input_file = os.fdopen(fd, 'rb') print('recv_fd:', input_file.read()) input_file.close()
spam.txt
:
Hello World!
実行結果
送信側 (サーバー側):
$ python3.5 send_fd.py
send_fd: b'Hello'
end
受信側 (クライアント側):
$ python3.5 recv_fd.py
recv_fd: b' World!\n'
サーバー側で最初の5バイト、クライアント側でその続きから読み出せている。
参考
https://docs.python.org/3/library/socket.html#socket.socket.sendmsg https://docs.python.org/3/library/socket.html#socket.socket.recvmsg