myhouse myhouse - 1 month ago 14
Ruby Question

communication between two clients in Ruby

I am trying to create a Ruby program that would send messages between two clients with the server in the middle. For example client A connects to server and client B connects to the same server and port. Client A says "How are you?" and client B says "Doing good." Kinda like a chat server. I am thinking on having the server take the message from client A and send to client B. So far I have this working client and server program that connects using a certificate. The problem I have is that my server sends back to client A and I do not know how to send to the second connection (client B).

client

#!/usr/bin/ruby
require "socket"
require "openssl"
require "thread"

host = ARGV[0]
port = Integer(ARGV[1])

socket = TCPSocket.new(host, port)
certificate = OpenSSL::X509::Certificate.new(File.open("server.crt"))
ssl = OpenSSL::SSL::SSLSocket.new(socket)
ssl.sync_close = true
ssl.connect
if ssl.peer_cert.to_s != certificate.to_s
stderrr.puts "Unexpected certificate"
exit(1)
end

# Get input through the server
Thread.new {
begin
while server_res = ssl.gets.chomp
puts server_res
end
rescue
$stderr.puts "Error in server response loop: " + $!
end
}
# send out the STDIN to the server
while (client_sent = STDIN.gets.chomp)
ssl.puts client_sent
end


server

#!/usr/bin/ruby

require "socket"
require "openssl"
require "thread"

port = Integer(ARGV[0])
server = TCPServer.new(port)

sslCont = OpenSSL::SSL::SSLContext.new
sslCont.cert = OpenSSL::X509::Certificate.new(File.open("server.crt"))
sslCont.key = OpenSSL::PKey::RSA.new(File.open("server.key"))

sslServ = OpenSSL::SSL::SSLServer.new(server, sslCont)

loop {
connection = sslServ.accept
Thread.new {
begin
while (client_sent = connection.gets) do
client_sent = client_sent.chomp
puts "Client Sent: " + client_sent
server_res = "Server Response: " + client_sent
puts server_res
connection.puts server_res
end
rescue
$stderr.puts $!
end
}
}

Answer
  • Keep an array of accepted connections

    connections = []
    
  • Keep it up to date when someone connects or disconnects

    connections << connection
    ...
    connections.delete(connection)
    
  • When sending, you can send to all of them:

    connections.each do |conn|
      conn.puts server_res
    end
    
  • Or just all except the current one:

    connections.each do |conn|
      next if conn == connection
      conn.puts server_res
    end
    
Comments