Usare le socket in Ruby
Sapete che non amo particolarmente Ruby, ma ho dovuto avere a che fare con le socket per un piccolo programma.
E quindi vi riporto qui il codice basico di partenza da cui sono partito.
Abbiamo due file per i nostri:
- server.rb
- client.rb
Partiamo dal server:
require 'socket'
class Server
def initialize(socket_address, socket_port)
@server_socket = TCPServer.open(socket_port, socket_address)
@connections_details = Hash.new
@connected_clients = Hash.new
@connections_details[:server] = @server_socket
@connections_details[:clients] = @connected_clients
puts 'Server attivato'
run
end
def run
loop{
client_connection = @server_socket.accept
Thread.start(client_connection) do |conn|
conn_name = conn.gets.chomp.to_sym
if(@connections_details[:clients][conn_name] != nil)
conn.puts "Lo username inserito già è connesso"
conn.puts "quit"
conn.kill self
end
puts "Connessione stabilita #{conn_name} => #{conn}"
@connections_details[:clients][conn_name] = conn
conn.puts "Connessione accettata per l'utente #{conn_name} => #{conn}, scrivi qualcosa"
send_message(conn_name, conn)
end
}.join
end
def send_message(username, connection)
loop do
message = connection.gets.chomp
puts @connections_details[:clients]
(@connections_details[:clients]).keys.each do |client|
@connections_details[:clients][client].puts "#{username} : #{message}"
end
end
end
end
Server.new(4000, "localhost")
Una volta avviato, il server rimane in attesa di una connessione; e del nome utente che verrà inserito nel client.
Facciamo anche un controllo che lo stesso utente non possa avere più di una connessione attiva.
Ma utenti diversi possono collegarsi allo stesso momento; come vedete usiamo un Thread per ogni connessione.
Lato client abbiamo questo:
require 'socket'
class Client
def initialize(socket)
@socket = socket
@request_object = send_request
@response_object = listen_response
@request_object.join
@response_object.join
end
def send_request
puts "Inserisci il tuo nome per la connessione"
begin
Thread.new do
loop do
message = $stdin.gets.chomp
@socket.puts message
end
end
rescue IOError => e
puts e.message
@socket.close
end
end
def listen_response
begin
Thread.new do
loop do
response = @socket.gets.chomp
puts "#{response}"
if response.eql?'quit'
@socket.close
end
end
end
rescue IOError => e
puts e.message
@socket.close
end
end
end
socket = TCPSocket.open("localhost", 4000)
Client.new(socket)
Ci verrà richiesto il nome utente; a connessione avvenuta possiamo inviare messaggi.
Per fare delle prove:
- avviate una sessione di terminale per il server
- avviate una sessione di terminale per il client inserendo un nome
- avviate una sessione di terminale per il client inserendo lo stesso nome sopra, per vedere che va in errore
- avviate una sessione di terminale per il client inserendo un nome diverso
In sostanza tre sessioni di terminale.
Enjoy!
ruby thread socket
Commentami!