tcp-echo-client.tcl 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #!/usr/bin/tclsh
  2. set read_running 0
  3. set write_running 0
  4. set read_eof 0
  5. set theend 0
  6. set nread 0
  7. set nwritten 0
  8. proc ReadBack {fd} {
  9. if { !$::write_running } {
  10. puts stderr "ERROR: connection closed unexpectedly!"
  11. set ::theend 1
  12. return
  13. }
  14. set r [read $fd 4096]
  15. if {$r == ""} {
  16. if {[eof $fd]} {
  17. puts stderr "EOF on socket"
  18. set ::read_running 0
  19. return
  20. }
  21. # --- puts stderr "SPURIOUS, not reading"
  22. return
  23. }
  24. # --- puts stderr "REPRINTING [string bytelength $r] bytes"
  25. puts -nonewline stdout $r
  26. incr ::nwritten [string bytelength $r]
  27. # --- puts stderr "DONE"
  28. set remain [expr {$::nread - $::nwritten}]
  29. if { $::read_eof } {
  30. puts stderr "Finishing... read=$::nread written=$::nwritten diff=[expr {$::nwritten - $::nread}] - [expr {100.0*$remain/$::nread}]%"
  31. }
  32. # Nothing more to read
  33. if {$remain == 0} {
  34. puts stderr "NOTHING MORE TO BE WRITTEN - exiting"
  35. set ::theend 1
  36. return
  37. }
  38. after idle "ReadBack $fd"
  39. }
  40. proc SendToSocket {fd} {
  41. global theend
  42. if { !$::write_running } {
  43. # --- puts stderr "SERVER DOWN, not reading"
  44. fileevent stdin readable {}
  45. return
  46. }
  47. if { $::read_eof } {
  48. # Don't read, already EOF.
  49. }
  50. # --- puts stderr "READING cin"
  51. set r [read stdin 4096]
  52. if {$r == ""} {
  53. if {[eof stdin]} {
  54. if {!$::read_eof} {
  55. puts stderr "EOF, setting server off"
  56. set ::read_eof 1
  57. }
  58. # Just enough when the next SendToSocket will
  59. # not be scheduled.
  60. return
  61. }
  62. # --- puts stderr "SPURIOUS, not reading"
  63. return
  64. }
  65. # --- puts stderr "SENDING [string bytelength $r] bytes"
  66. # Set blocking for a short moment of sending
  67. # in order to prevent losing data that must wait
  68. fconfigure $fd -blocking yes
  69. puts -nonewline $fd $r
  70. incr ::nread [string bytelength $r]
  71. fconfigure $fd -blocking no
  72. # --- if {[fblocked stdin]} {
  73. # --- # Nothing more to read
  74. # --- return
  75. # --- }
  76. after idle "SendToSocket $fd"
  77. }
  78. set fd [socket {*}$argv]
  79. fconfigure $fd -encoding binary -translation binary -blocking no -buffering none
  80. fileevent $fd readable "ReadBack $fd"
  81. fconfigure stdin -encoding binary -translation binary -blocking no
  82. fconfigure stdout -encoding binary -translation binary
  83. fileevent stdin readable "SendToSocket $fd"
  84. # --- puts stderr "READY, sending"
  85. set read_running 1
  86. set write_running 1
  87. vwait theend
  88. close $fd