UNIXSocket 클래스

UNIXSocket 클래스

UNIXSocketUNIX 도메인 스트림 클라이언트 소켓을 나타내는 클래스예요. UNIXServer가 서버 쪽이라면, UNIXSocket은 그 서버에 연결하는 클라이언트 쪽이에요. 경로(path) 기반으로 같은 머신 안의 프로세스들과 통신해요.

출처: Ruby 4.0 API — UNIXSocket

Public Class Methods

new(path) → unixsocket

path에 연결된 새 UNIX 클라이언트 소켓을 만들어요.

require 'socket'

s = UNIXSocket.new("/tmp/sock")
s.send "hello", 0

pair([type [, protocol]]) → [unixsocket1, unixsocket2]

서로 연결된 소켓 한 쌍을 만들어요. socketpair을 이용한 방식이라, 프로세스 하나에서 양방향 통신 파이프처럼 쓸 수 있어요.

type은 소켓 타입으로 :STREAM, :DGRAM, :RAW 등을 줄 수 있어요. protocol은 도메인에 정의된 프로토콜이며, 기본값 0이 도메인의 기본 프로토콜이에요.

s1, s2 = UNIXSocket.pair
s1.send "a", 0
s1.send "b", 0
p s2.recv(10) #=> "ab"

pair는 인자를 생략하면 기본적으로 SOCK_STREAM 타입의 소켓 쌍을 만들어요. 스트림이라 s1이 보낸 "a"와 "b"가 s2에서 하나의 스트림 "ab"로 이어져 받아지는 걸 볼 수 있어요.

Public Instance Methods

addr → [address_family, unix_path]

로컬 주소를 address_familyunix_path를 담은 배열로 돌려줘요.

serv = UNIXServer.new("/tmp/sock")
p serv.addr #=> ["AF_UNIX", "/tmp/sock"]

path → path

소켓의 로컬 주소 경로를 돌려줘요.

s = UNIXServer.new("/tmp/sock")
p s.path #=> "/tmp/sock"

peeraddr → [address_family, unix_path]

상대(원격) 주소를 address_familyunix_path를 담은 배열로 돌려줘요. 연결된 상대방의 경로를 알고 싶을 때 써요.

serv = UNIXServer.new("/tmp/sock")
c = UNIXSocket.new("/tmp/sock")
p c.peeraddr #=> ["AF_UNIX", "/tmp/sock"]

recv_io([klass [, mode]]) → io

UNIX 도메인 소켓의 **파일 디스크립터 전달(fd passing)**로 받은 IO를 돌려줘요. 상대가 send_io로 보낸 파일 디스크립터를 이 메서드로 받는 거예요.

UNIXServer.open("/tmp/sock") {|serv|
  UNIXSocket.open("/tmp/sock") {|c|
    s = serv.accept

    c.send_io STDOUT
    stdout = s.recv_io

    p STDOUT.fileno #=> 1
    p stdout.fileno #=> 7

    stdout.puts "hello" # "hello\n"을 표준 출력으로 출력
  }
}

klass는 반환되는 io의 클래스를 결정해요(IO.for_fd 싱글턴 메서드 등을 사용). klassnil이면 정수 파일 디스크립터가 반환돼요. modeIO.for_fd에 넘기는 인자와 같아요.

recvfrom(maxlen [, flags[, outbuf]]) → [mesg, unixaddress]

unixsocket을 통해 메시지를 받아요.

maxlen은 받을 최대 바이트 수예요. flagsSocket::MSG_* 상수들의 비트 OR이에요. outbuf는 메서드 호출 전에 비어 있지 않아도, 호출 후에는 받은 데이터만 담겨요.

s1 = Socket.new(:UNIX, :DGRAM, 0)
s1_ai = Addrinfo.unix("/tmp/sock1")
s1.bind(s1_ai)

s2 = Socket.new(:UNIX, :DGRAM, 0)
s2_ai = Addrinfo.unix("/tmp/sock2")
s2.bind(s2_ai)
s3 = UNIXSocket.for_fd(s2.fileno)

s1.send "a", 0, s2_ai
p s3.recvfrom(10) #=> ["a", ["AF_UNIX", "/tmp/sock1"]]

send_io(io) → nil

io파일 디스크립터 전달로 보내요. 상대 쪽에서 recv_io로 받을 수 있어요. 같은 머신의 프로세스끼리 파일 디스크립터를 넘겨줄 때 쓰는 기법이죠.

s1, s2 = UNIXSocket.pair

s1.send_io STDOUT
stdout = s2.recv_io

p STDOUT.fileno #=> 1
p stdout.fileno #=> 6

stdout.puts "hello" # "hello\n"을 표준 출력으로 출력

io에는 어떤 종류의 IO 객체든, 또는 정수 파일 디스크립터든 넘길 수 있어요.