Usare le socket in Ruby

Mattepuffo's logo
Usare le socket in Ruby

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!

Fonte


Condividi

Commentami!