#!/bin/bash # # Copyright (c): Uwe Schmidt, FH Wedel # # You may study, modify and distribute this source code # FOR NON-COMMERCIAL PURPOSES ONLY. # This copyright message has to remain unchanged. # # Note that this document is provided 'as is', # WITHOUT WARRANTY of any kind either expressed or implied. #!/bin/bash # the next line restarts using tclsh \ exec tclsh "$0" "$@" # $Id: echoserver.tcl,v 1.2 2006/01/08 14:20:20 uwe Exp $ # global state init -------------------- set state(wait) 1 set state(openSock) {} source setopt.tcl source message.tcl proc evalOptions args { global state setopt port 4242 setopt trace 2 setopt chat 0 set state(port) $port set state(trace) $trace set state(chat) $chat message 2 "port: $state(port)" message 2 "chat: $state(chat)" } # the data processing -------------------- # # here: do nothing, just send the data back proc echoData {socket req} { sendAnswer $socket $req } # here: do nothing, just distribute the data to all clients proc chatData {socket req} { global state foreach soc $state(openSock) { sendAnswer $soc $req } } # socket communication -------------------- proc sendAnswer {socket ans} { if {[catch \ { puts $socket $ans flush $socket } err]} { message 1 "sendAnswer($socket): error: $err" closeServer $socket return } message 3 "sendAnswer($socket): message written: $ans" } proc processRequest {socket} { if {[catch \ { set cnt [gets $socket req] } err]} { message 1 "processRequest($socket): $err" set cnt -1 } if {$cnt == -1} { closeServer $socket return } message 3 "processRequest($socket): message read: $req" processData $socket $req global state set state(wait) 1 } proc openServer {socket args} { global state message 2 "openServer: install file event on $socket" lappend state(openSock) $socket fileevent $socket readable "processRequest $socket" } proc closeServer {socket} { global state message 2 "closeServer: close socket $socket" close $socket set i [lsearch -exact $state(openSock) $socket] set state(openSock) [lreplace $state(openSock) $i $i] if {"$state(openSock)" == ""} { message 2 "closeServer: server idle, no open connections" } } proc initServer {} { global state message 2 "initServer: port is $state(port)" if {[catch {socket -server openServer $state(port)} err]} { message 1 "initServer failed: $err" exit } } proc eventLoop {} { global state while {1} { vwait state(wait) message 3 "eventLoop: do one event" update } } proc init {} { global argv state eval evalOptions $argv if {$state(chat) == 1} { rename chatData processData } else { rename echoData processData } initServer eventLoop } init