a simple chat server

rmax wrote this server during his presentation at FOSDEM 2004 while the audience wrote chat clients.


 if {![info exists sock]} {
    set sock [socket -server connect 7654]
 }

 proc connect {sock host port} {
    fconfigure $sock -blocking 0 -buffering line
    fileevent $sock readable [list handleSocket $sock]
    set ::socks($sock) $sock
 }

 #disconnect IS NOT BEING USED ANYWHERE
 proc disconnect {sock args} { 
    set nick $::socks($sock)
    unset ::socks($sock)
    close $sock
    sendText "* $nick has left the chat: [join $args]"
 }

 proc handleSocket {sock} {
    gets $sock line
    if {[eof $sock]} {
        unset ::socks($sock)   ;#Before closing socket, it needs to be unset.
        close $sock
        return
    }
    if {$line eq ""} return
    if {[string index $line 0] eq "/"} {
        set cmd [split  $line]
        set cmd [linsert $cmd 1 $sock]
        if {[catch {eval $cmd} error] != 0} {
            puts $sock "* $error"
            return
        }
    } else {
        sendText "$::socks($sock): $line"
    }
 }

 proc sendText {text} {
    foreach s [array names ::socks] {
        puts $s $text
    }
 }

 proc /msg {sock args} {
    set found 0
    if {[llength $args] < 2} {
        puts $sock "* usage: /msg nick message"
        return
    }
    set nick [lindex $args 0]
    set message [join [lrange $args 1 end]]
    foreach {s n} [array get ::socks] {
        if {$n eq $nick} {
            set found 1
            break
        }
    }
    if {$found} {
        puts $s "$::socks($sock) whispers $message"
    }
 }

 proc /nick {sock args} {
    if {[llength $args] != 1} {
        puts $sock "* usage: /nick newnick"
    } else {
        set newnick [lindex $args 0]
        set ::socks($sock) $newnick
    }
 }

 proc /who {sock args} {
    if {[llength $args]} {
        puts $sock "* usage: /who"
    } else {
        set nicks "* nicks:"
        foreach {_ nick} [array get ::socks] {
            append nicks " $nick"
        }
    }
    puts $sock $nicks
 }

 vwait forever

See also: A little Chat Server