A Tcl programozási nyelv

Példaprogramok



Érdekes Tcl eljárások

# decr változónév ?érték?
# Az incr parancs párja.

proc decr {name {value 1}} {
    upvar 1 $name $name

    incr $name [expr - $value]
}

# sum ?érték ...?
# A megadott értékek összegét adja vissza.

proc sum {args} {
    set s 0
    foreach v $args {
	set s [expr $s+$v]
    }
    return $s
}

# do változó kezdő határ törzs
# A 'for {set változó kezdő} {$változó <= határ} {incr változó} törzs' ciklus
# megfelelője.

proc do {varName first last body} {
    upvar $varName v

    for {set v $first} {$v <= $last} {incr v} {
	uplevel $body
    }
}

# repeat n törzs
# A törzset megismétli n-szer.  Fejlett kivételkezelés.

proc repeat {count body} {
    global errorInfo errorCode

    if {[catch {incr count -1} retval]} then {
	return -code error $retval
    }
    while {$count >= 0} {
	set retcode [catch {uplevel $body} retval]
	switch $retcode {
	    0 {}
	    1 {
		set trace [split $errorInfo \n]
		set tracelen [llength $trace]
		set line3 [lindex $trace [expr $tracelen - 3]]
		regsub uplevel $line3 repeat line3
		set trace [concat [lrange $trace 0 [expr $tracelen - 4]] \
			[list $line3]]
		set errorInfo [join $trace \n]		
		return -code error -errorinfo $errorInfo -errorcode $errorCode\
		    $retval}
	    3 {return}
	    4 {}
	    default {return -code $retcode $retval}

	}
	incr count -1
    }
    return
}

# debug változó index művelet
# A 'trace variable változónév rwu debug' paranccsal nyomon követi egy változó
# olvasását, írását és törlését.

proc debug {name element op} {
    if {[string compare $element ""] == 0} then {
	set varname $name
    } else {
	set varname $name\($element\)
    }
    puts -nonewline "debug: '$varname' was "
    puts [switch $op r {expr {"read"}} w {expr {"written"}} u {expr {"unset"}}]
    if {[string compare $op u] != 0} then {
	upvar $varname x
	puts "debug: '$varname' = '$x'"
    }
}

Egy önálló Tcl programocska

#!/bin/sh
# Simple Tcl implementation of grep. \
exec tclsh "$0" "$@"

proc grep {prefix file} {
    global argv

    set pattern [lindex $argv 0]
    while {[gets $file line] >= 0} {
	if {[regexp -- $pattern $line]} then {
	    puts "$prefix$line"
	}
    }
}

if {$argc < 1} {
    error "Usage: tgrep pattern ?fileName?"
}
if {$argc == 1} then {
    grep "" stdin
} else {
    foreach fname [lrange $argv 1 end] {
	set file [open $fname r]
	grep "$fname:" $file
	close $file
    }
}

Tcp programozás tcl-ben

Bevezetés

A Tcl-ben lehetőség van TCP alapú szerver-kliens rendszerek programozására. A TCP kapcsolatok file handler-ekkel vannak reprezentálva, amelyekre a közönséges állományokat azonosító file handler-ekhez hasonlóan lehet a szabványos állománykezelő parancsokat alkalmazni. A TCP kapcsolat felépítése a socket parancs segítségével történik. A file handler-ek tulajdonságait a fconfigure parancs segítségével lehet változtatni.

Kliens kapcsolat létrehozása

A socket parancsnak két változata létezik, az egyik TCP kliens kapcsolat, a másik TCP szerver létrehozását végzi.

socket <kapcsolók> host port
A parancs a host host port port-jához kliensként próbál csatlakozni. A parancs visszatérési értéke a kapcsolatot azonosító file handler. A file handler-be írva, vagy innén olvasva a szabványos filekezelő műveletekkel lehet a szerverhez adatot eljuttatni, vagy a szervertol adatot kapni.

A host a host domainneve vagy IP címe lehet, ez utóbbit a szokásos pontokkal szeparált alakban kell megadni, pl.: 153.34.5.6. A port egy egész szám, amely annak a portnak a sorszámát adja meg, amelyhez csatlakozni akarunk. Lehetőség van annak meghatározására, hogy a kliens kapcsolat felépítésénél melyik hálózati interface-t használja a rendszer ( egy nagyobb gépen esetenként több hálózati eszköz, és így több hálózati felület érheto el) .

Egy másik fontos lehetőség az aszinkron kapcsolat-felépítés lehetősége. Alapesetben a socket parancs csak akkor tér vissza. amikor a a szerver-kliens kapcsolatot sikerült kiépítenie. De megfelelő kapcsolók megadásával lehetőség van arra, hogy a socket parancs már azelőtt visszatérjen, mielőtt sikerült volna kapcsolódnia a megadott szerverhez. Ha ezek után gets vagy flush parancsot adunk ki a visszaadott állomány azonosítóra, akkor két eset lehetséges:

Azt, hogy egy állomány azonosító blocking, vagy nonblocking módban legyen a fconfigure paranccsal lehet beállítani.

A <kapcsolók> a következő értékeket veheti fel:

-myaddr addr
a használni kívánt lokális hálózati interface-t adja meg. Az addr lehet domain-név, vagy IP cím. Ha nem adjuk meg ezt a kapcsolót, akkor az interface megválasztása automatikusan történik.
-myport port
a lokális portot adja meg, a port tartalmazza a használni kívánt port sorszámát.
-async
Ha ezt az opciót adjuk meg, akkor a kapcsolat felépítése aszinkron módon történik, a fentiekben leírtak szerint.

TCP szerver programozása

socket -server parancs <kapcsolók> port
A parancs lefutása után egy állomány azonosítót add vissza. Ebben az állomány azonosítóba nem lehet sem írni és nem lehet belőle olvasni. Ha az elindított szerverhez kérés érkezik kapcsolat létesítésére, akkor a szerver felépíti a kapcsolatot, állomány leírót rendel hozza és elindítja a parancs utasítást három plusz paraméterrel: a kapcsolatot azonosító állomány leíró, a kliens host címe, a kliens portszáma. Ha a socket parancs által visszaadott állomány azonosítót bezárjuk, akkor a szerver már nem fog újabb kéréseket fogadni, de a már elfogadott kérések kiszolgálása végre fog hajtódni. A <kapcsolók> felveheti a -myaddr addr értéket, ahol addr a használni kívánt hálózati interface címe. Ha a fenti opciót megadjuk a parancsnak, akkor az addr által meghatározott hálózati interface-n fogja futtatni a szervert. A szerver működése a Tcl eseménykezelőjétől függ. Ha a script nem lép be a Tcl eseménykezelő ciklusába, akkor a szerver egyetlen egy kérést sem fog fogadni.

Az fconfigure parancs

Az fconfigure utasítás az állomány azonosítók tulajdonságainak beállítását végzi. Az állomány azonosítók bizonyos tulajdonságai függetlenek attól, hogy milyen fizikai eszközt ír le az állomány azonosító, más tulajdonságok más-más jelentéssel bírnak attól függoen, hogy az állomány azonosító milyen fizikai eszközt ír le. Vannak olyan tulajdonságok is, amelyek csak bizonyos fizikai eszközöket leíró állomány azonosítók esetén vannak értelmezve, pl. a socket-eknek speciális tulajdonságai vannak. Az fconfigure szintaxisa:

fconfigure <file handler>
A <file handler> file azonosítóval kapcsolatos különféle kapcsolók neveit és az aktuális értékeit tartalmazó listát ad vissza.
fconfigure <file handler> név
A <file handler> file azonosító név kapcsolójának aktuális értékt adja vissza.
fconfigure <file handler> név érték ? név érték ? ...
Minden név érték párra a <file handler> adott nevu kapcsolóját a megadott értékre állítja be.

A TCP programozása szempontjából a következő kapcsolók lehetnek fontosak:

-blocking
Logikai értéket vehet fel, ha igazra van állítva (ez az alapértelmezés) akkor az I/O műveletek szinkron módon hajtódnak végre. Ha ez az érték hamisra van állítva, akkor az I/O műveletek aszinkron módon hajtódnak végre, azaz, ha a műveleteket nem sikerült azonnal végrehajtani, akkor a muveletet meghívó programrész visszakapja a vezérlést.
-sockname
Csak socket típusú file azonosítókra érvényes kapcsoló. Három elemből álló listát ad vissza hatására a program , amely a socket címét, a sockethez tartozó port számát, és a távoli gép nevét tartalmazza
-peername
Csak a server-kliens kapcsolat kliens részét reprezentáló socketeknek megfelelő file azonosítókra van értelmezve. Hatására az fconfigure parancs egy háromelemű listát ad vissza, amely a socket címét, a távoli szerver gép nevét és annak a portnak a számát tartalmazza, amelyhez csatlakozik a socket által leírt kliens.