An almost canonical use case for threads is for writing servers that can communicate with more than one client at a time.
[~/ruby/threads(master)]$ cat simple_server.rb require 'socket' # This method expects a socket connected to a client. # It reads lines from the client, reverses them and sends them back. # Multiple threads may run this method at the same time. def handle_client(c) while true input = c.gets.chop # Read a line of input from the client p "Received <#{input}>" break if !input # Exit if no more input break if input=="quit" # or if the client asks to. yield c, input c.flush # Force our output out end c.close # Close the client socket end port = ARGV.shift || 2000 server = TCPServer.open(port) p "listening in port #{port}" while true # Servers loop forever client = server.accept # Wait for a client to connect p "new client: #{client}" Thread.start(client) do |c| # Start a new thread handle_client(c) do |c, input| # And handle the client on that thread c.puts(input.reverse) end end end
.open
to specify a port for your service and
create a TCPServer object
accept
method of the returned TCPServer object
Thread.start(client)
is basically the same as a call to Thread.new
.
handle_client
method, passing the socket
as argument
handle_client
specifies the behavior
of the server.
>> TCPSocket.ancestors => [TCPSocket, IPSocket, BasicSocket, IO, File::Constants, Enumerable, Object, Kernel, BasicObject]
To obtain a TCPSocket instance use the TCPSocket.open
class method, or with its synonym TCPSocket.new
.
Pass the name of the host to connect to as the first argument and the port as the second argument.
The port should be an integer between 1 and 65535, specified as a Fixnum or String object.
Different internet protocols use different ports.
Web servers use port 80 by default, for example.
You may also pass the name of an Internet service, such as http
, as a string, in place of a port number, but this is not well documented and may be system dependent.
[~/ruby/threads(master)]$ cat simple_client.rb require 'socket' # Sockets are in standard library host, port = 'localhost', '2000' s = TCPSocket.open(host, port) # Open a socket to host and port words = ARGV words = [ "amore, roma.", "a man, a plan, a canal: panama.", "no 'x' in 'nixon.'", "dábale arroz a la zorra el abad" ] unless words.length > 0 words.each do |x| s.puts x line = s.gets # Read lines from the socket break if line.nil? puts line.chop # And print with platform line terminator end s.close # Close the socket when done
[~/ruby/threads(master)]$ ruby simple_server.rb "listening in port 2000" "new client: #<TCPSocket:0x007fd8fb8aee50>" "Received <amore, roma.>" "Received <a man, a plan, a canal: panama.>" "Received <no 'x' in 'nixon.'>" "Received <d\xC3\xA1bale arroz a la zorra el abad>"
[~/ruby/threads(master)]$ ruby simple_client.rb .amor ,eroma .amanap :lanac a ,nalp a ,nam a '.noxin' ni 'x' on
Casiano Rodriguez León 2015-01-07