eltiare (owner)

Revisions

gist: 79458 Download_button fork
public
Public Clone URL: git://gist.github.com/79458.git
simple_chat_server.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# Please note that I adapted this code from an ancient (5 year old) article on IBM's site.
# I Forget the URL...
require "socket"
class ChatServer
  def initialize( port )
    @sockets = []
    @port = port
  end # initialize
  
  def run
    if @this_thread then false
    else
      @server_socket = TCPServer.new( "", @port )
      @server_socket.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
      printf("Chatserver started on port %d\n", @port)
      @sockets.push( @server_socket )
      
      @this_thread = Thread.new(@server_socket, @sockets) { |server_socket, sockets|
        while true
          res = select( sockets, nil, nil, 0 )
          if res
            # Iterate through the tagged read descriptors
            res[0].each do |sock|
              # Received a connect to the server (listening) socket
              if sock == server_socket
                accept_new_connection
              else
                # Received something on a client socket
                if sock.eof?
                  str = sprintf("Client left %s:%s\n", sock.peeraddr[2], sock.peeraddr[1])
                  broadcast_string( str, sock )
                  sock.close
                  sockets.delete(sock)
                else
                  str = sprintf("[%s|%s]: %s", sock.peeraddr[2], sock.peeraddr[1], sock.gets())
                  broadcast_string( str, sock )
                end#if
              end#if
            end#each
          end#if
        end#while
      }
      @this_thread.run
      true
    end#if
  end#def
 
  def stop
    @this_thread.kill if @this_thread
    @sockets.each { |socket| socket.close }
    @sockets = []
    @this_thread = nil
  end
  
  private
  
    def broadcast_string( str, omit_sock )
      puts str
      @sockets.each { |client_sock| client_sock.puts(str) unless client_sock == @server_socket || client_sock == omit_sock }
    end
    
    def accept_new_connection
      new_sock = @server_socket.accept
      @sockets.push new_sock
      new_sock.puts("You're connected to the Ruby chatserver")
      str = sprintf("Client joined %s:%s", new_sock.peeraddr[2], new_sock.peeraddr[1])
      broadcast_string( str, new_sock )
    end # accept_new_connection
  
end #server