A socket pair is a pair of already connected sockets. This is very useful for two way inter process communication (IPC).
man 2 socket says:
socket - create an endpoint for communication
socket()creates an endpoint for communication and returns a descriptor.
A socket pair will give you two sockets. The parent can then fork a child. The child will use one of the pairs and the parent the other. Each process has access to both sockets. A typical pattern is to close the one socket that you are not using. The child will choose one and the parent the other.
To create a Unix socket pair in ruby is quite easy.
socket1, socket2 = UNIXSocket.pair(:STREAM) # Creates a pair of sockets connected each other.
Unix sockets are special because they are only available to the local system. Another additional benefit is that you can pass file descriptors across a unix socket.
In this example I create a unix socket pair. The child process reads/writes to/from socket2. The parent process reads/writes to/from socket1. I used the netstring protocol to send and receive the data.
require "socket"
class NetString
LENGTH_SIZE = [1].pack("I").size
def initialize(socket)
@socket = socket
end
def receive()
bytes_to_read = @socket.read(LENGTH_SIZE).unpack("I").first
message = @socket.read(bytes_to_read)
p "received: #{message} in process #{Process.pid}"
message
end
def send(data)
p "sending: #{data} from process #{Process.pid}"
bytes_to_write = [data.size].pack("I")
@socket.write(bytes_to_write)
@socket.write(data)
end
end
socket1, socket2 = UNIXSocket.pair(:STREAM)
fork do
socket1.close
socket = NetString.new(socket2)
socket.send(socket.receive().reverse)
end
socket2.close
socket = NetString.new(socket1)
socket.send("taco cat")
socket.receive()
Process.waitall
The parent process sends the message “taco cat” to the child process. The child process reads that data from the socket and then reverses it and writes it back to the socket.
The output on my screen is:
λ ruby netstring.rb
"sending: taco cat from process 3594"
"received: taco cat in process 3596"
"sending: tac ocat from process 3596"
"received: tac ocat in process 3594"