This blog post is an introduction to TCP socket server programming and thread programming in Ruby 1.8. It also illustrates how compact and expressive Ruby code can be. The intended audience is Ruby beginners.
require 'socket' # TCPServer ss = TCPServer.new(1233) loop { Thread.start(ss.accept) { |s| begin while line = s.gets; # Returns nil on EOF. (s << "You wrote: #{line.inspect}\r\n").flush end rescue bt = $!.backtrace * "\n " ($stderr << "error: #{$!.inspect}\n #{bt}\n").flush ensure s.close end } }
Use telnet 127.0.0.1 1233
to connect to the echo server as a new participant, and then type your chat message(s) terminated by Enter (newline). The echo server sends back each message it receives with the You wrote boilerplate around it. Multiple independent clients can connect to the chat server at a time.
The chat server:
require 'socket' # TCPServer require 'thread' # Queue ssock = TCPServer.new(1234) msgs = Queue.new participants = [] Thread.start { # Send chat messages to participants. while msg = msgs.pop; # Always true. participants.each { |s| (s << msg).flush rescue IOError } end } loop { Thread.start(ssock.accept) { |sock| participants << sock begin while line = sock.gets; # Returns nil on EOF. msgs << ": #{line.chomp!}\r\n" end rescue bt = $!.backtrace * "\n " ($stderr << "error: #{$!.inspect}\n #{bt}\n").flush ensure participants.delete sock sock.close end } }
Use telnet 127.0.0.1 1234
to connect to the chat server as a new participant, and then type your chat message(s) terminated by Enter (newline). The chat server sends each message (with a colon prepended) to all connected participants.
The Ruby source files above demonstrate the following:
- how to create a thread
- how to use thread-local variables (e.g. sock)
- how to report exceptions in a thread
- how to ignore IOError
- how to read a line from a socket
- how to use the Queue class for synchronization between threads
- how to clean up using an ensure block
- how to pass values to a newly created thread
No comments:
Post a Comment