'''[http://netcat.sourceforge.net%|%netcat]''' is a tool for connecting I/O streams to [network programming%|%sockets]. From the web site: ''Netcat is a featured networking utility which reads and writes data across network connections, using the TCP/IP protocol. It is designed to be a reliable "back-end" tool that can be used directly or easily driven by other programs and scripts. At the same time, it is a feature-rich network debugging and exploration tool, since it can create almost any kind of connection you would need and has several interesting built-in capabilities.'' Also see: http://en.wikipedia.org/wiki/Netcat ** JBR's implementation ** [JBR] 2012-11-06: I was using netcat on Ubuntu Linux to send some commands to a server and get the return data into my processing pipe. The server can take some time to compute the answer (an image) and respond, so I wanted the client (nc) to wait forever for the data after reading the commands from stdin. I used the "-q" flag with -1 as a argument. Now sitting at home on my MacBook, I find that the OS X version of netcat doesn't have this flag. I poked around on the net to see if I could find the Ubuntu versions's source but I haven't found it yet. I thought that it should be easy enough to do what I want in Tcl. So I wrote this, but it doesn't work either, it won't read any lines from stdin: ====== #! /usr/bin/env tclkit8.6 set host [lindex $argv 0] set port [lindex $argv 1] set sock [socket $host $port] fconfigure $sock -translation binary fcopy $sock stdout -command exit while { [gets stdin line] >= 0 } { puts $sock $line } close $sock w vwait forever ====== [RLE] 2012-11-07: You are not properly entering the event loop here if you are looking to make a "nc" substitute. You need to setup [fileevent] bindings on both your socket and on stdin, and do your read/copy from the socket or stdin from within the fileevent handlers. ** dbohdan's implementation ** [dbohdan] 2015-08-13: The following is my take on `netcat` in Tcl. It is event-based and mildly scriptable. In theory it should be possible to use from other Tcl applications and can handle multiple simultaneous connections as long as they don't use the same channels as each other (i.e., only one connection can access the `stdin` and the `stdout`). However, I have not tested that functionality extensively. Download with [wiki-reaper]: `wiki-reaper -x 14702 1 15 > netcat-0.1.0.tcl` ====== #!/usr/bin/env tclsh # An event-based netcat clone for Tcl 8.5+, version 0.1.0 (2015-08-13). # Written by dbohdan. # License: MIT. namespace eval ::netcat { variable bufferSize 4096 variable connectionCount 0 variable connections } proc ::netcat::copy-when-readable {chanFrom chanTo} { puts -nonewline $chanTo [read $chanFrom $::netcat::bufferSize] if {[eof $chanFrom]} { close $chanFrom delete-connection $chanFrom } } proc ::netcat::delete-connection chan { variable connections set n [dict get $connections $chan] foreach {key _} [dict filter $connections value $n] { dict unset connections $key } set varName [gen-variable-name $n] set $varName 1 } proc ::netcat::gen-variable-name n { return [namespace current]::nc${n}Done } proc ::netcat::connect {host port {inputChan stdin} {outputChan stdout} {prelude {}}} { set socket [socket $host $port] fconfigure $socket -blocking 0 -translation binary -buffering none fconfigure $inputChan -blocking 0 -translation binary -buffering none fconfigure $outputChan -blocking 0 -translation binary -buffering none fileevent $socket readable [ namespace code [list copy-when-readable $socket $outputChan]] fileevent $inputChan readable [ namespace code [list copy-when-readable $inputChan $socket]] apply [list socket $prelude] $socket variable connectionCount variable connections set n $connectionCount incr connectionCount dict set connections $socket $n dict set connections $inputChan $n dict set connections $outputChan $n set varName [gen-variable-name $n] set $varName 0 return $varName } # If this is the main script... if {[info exists argv0] && ([file tail [info script]] eq [file tail $argv0])} { lassign $argv host port preludeScript if {($host eq {}) || ![string is integer -strict $port]} { set u {} append u "usage: $argv0 host port \[preludeScript\]\n" append u "\nThe optional parameter preludeScript is a Tcl script " append u "that can manipulate the connection socket after the " append u "connection is established but before any input is " append u "transmitted or any received data is output. Example:\n" append u "\t$argv0 localhost 7777 'puts \$socket \$::env(REMOTE_ADDR)'" puts $u exit 1 } else { vwait [::netcat::connect $host $port stdin stdout $preludeScript] } } ====== <>Internet | Networking | Package