I have set up a simple tcl server which can be accessed in https://elotor-tcl-http-server-demo.hf.space/
proc Server {startTime channel clientaddr clientport} {
puts "Connection from $clientaddr registered"
fconfigure $channel -buffering line
fileevent $channel readable [list Echo $channel $startTime]
}
proc Echo {sock startTime} {
if { [catch {gets $sock line}] || [eof $sock] } {
close $sock
return
}
set now [clock seconds]
set htmlContent "
<!DOCTYPE html>
<html>
<head><title>Test Page</title></head>
<body><h1>Hello World</h1>
[expr {$now - $startTime}] seconds since start.</br>$line</body>
</html>
"
puts $sock "HTTP/1.1 200 OK"
puts $sock "Content-Type: text/html"
puts $sock "Content-Length: [string length $htmlContent]"
puts $sock ""
puts $sock $htmlContent
puts $sock "EOF"
flush $sock
close $sock
}
socket -server [list Server [clock seconds]] -myaddr 0.0.0.0 7860
proc bgerror msg {
puts stderr "[clock format [clock seconds]] $msgn$::errorInfo"
}
vwait forever
I’m considering using threads instead of events, but I don’t know if it is worth it, nor how to do it.
I tried the approach from https://www.activestate.com/blog/concurreny-tcl-weaving-threads/
package require Thread
proc NewConnection {startTime channel clientaddr clientport} {
puts "Connection from $clientaddr registered"
set t [thread::create {
proc HandleConnection {channel startTime} {
fconfigure $channel -buffering none
set data {}
while {![eof $channel]} {
if {[gets $channel line] < 0} {
continue
}
append data $line n
}
set now [clock seconds]
set htmlContent "
<!DOCTYPE html>
<html>
<head><title>Test Page</title></head>
<body><h1>Hello World</h1>
[expr {$now - $startTime}] seconds since start.</br>$line</body>
</html>
"
puts $channel {HTTP/1.1 200 OK}
puts $channel {Content-Type: text/html}
puts $channel "Content-Length: [string length $htmlContent]"
puts $channel {}
puts $channel $htmlContent
puts $channel EOF
close $channel
thread::release
}
thread::wait
}]
thread::transfer $t $channel
thread::send -async $t [list HandleConnection $channel $startTime]
}
socket -server _Accept -myaddr 0.0.0.0 7860
proc _Accept {s ipaddr port} {
after idle [list NewConnection [clock seconds] $s $ipaddr $port]
}
proc bgerror msg {
puts stderr "[clock format [clock seconds]] $msgn$::errorInfo"
}
vwait forever
But I get the following error:
Connection from XX.XX.XX.XX registered
Error from thread tid0x7f2693dddb38
error writing "sock7f2693e25e00": broken pipe
while executing
"puts $channel {HTTP/1.1 200 OK}"
(procedure "HandleConnection" line 19)
invoked from within
"HandleConnection sock7f2693e25e00 1714214861"
Connection from XX.XX.XX.XX registered
Error from thread tid0x7f2693d46b38
error writing "sock7f2693e26080": broken pipe
while executing
"puts $channel {HTTP/1.1 200 OK}"
(procedure "HandleConnection" line 19)
invoked from within
"HandleConnection sock7f2693e26080 1714214862"
Connection from XX.XX.XX.XX registered
Error from thread tid0x7f2693c8fb38
error writing "sock7f2693e26380": broken pipe
while executing
"puts $channel {HTTP/1.1 200 OK}"
(procedure "HandleConnection" line 19)
invoked from within
"HandleConnection sock7f2693e26380 1714214863"
Connection from XX.XX.XX.XX registered
Error from thread tid0x7f2693b98b38
error writing "sock7f2693e26e20": broken pipe
while executing
"puts $channel {HTTP/1.1 200 OK}"
(procedure "HandleConnection" line 19)
invoked from within
"HandleConnection sock7f2693e26e20 1714214864"