Message Boards Message Boards

1 Reply
2 Total Likes
View groups...
Share this post:

How to specify a TCPIP port in OpenWrite to talk to a netcat session ?

Posted 11 years ago
I want Mathematica to talk to a legacy code which expects telnet or netcat communications, and life being so short, I would prefer not to use MathLink (WolframLink). On a Mac (OSX) machine I start a netcat session in a Terminal window with:
$ nc -l 1234
which opens port 1234 for listening. If I start another netcat session in a second Terminal window with:
$ nc localhost 1234
then whatever you type in the first window will be echoed to the second and vice versa which simulates the required behaviour.
Then I hoped that this behaviour could be duplicated with Mathematica replacing the second Terminal window, using a stream to the open port from Mathematica, using:
out = OpenWrite["1234@localhost"]
WriteString[out, "Hello Dave "]
but nothing is received by the running netcat session. I looked for documentation on how to specify a TCPIP port in OpenWrite and OpenRead but came up empty handed. Any hints? Can the Read and Write commands send to and receive from TCPIP ports in something like the manner suggested above?
I spent several more hours on this topic today and here report some progress. I know this sounds very obscure, but something seriously cool may come of this. The following shows a hack that mostly works, to allow Mathematica to do 2-way communication with a netcat session on a local or remote machine. The hack is that I had to set up a stream that used netcat itself. So this is not as portable across platforms as I would like, and is not reading and writing directly to ports. To improve reliability, I have to open and close streams on each invocation, which must be hurting speed.
 rnc::usage =
   "rnc[machine,port] reads a string from a netcat session running on \
 a local or remote machine on the specified port. Start the netcat \
 session with $ nc -l -k <port>.";
 wnc::usage = [/size]
   "wnc[string,machine,port] writes a string to a netcat session \
 running on a local or remote machine on the specified port. Start the \
 netcat session with $ nc -l -k <port>.";

Clear[rnc, wnc];[/size]
rnc[machinename_String: "localhost", port_Integer: 1234] :=
  Map[Close, Complement[Streams[], Take[Streams[], 2]]] ;
  istr = OpenRead["!nc " <> machinename <> " " <> ToString[port]];
   Read[istr, Record]]

wnc[text_String: "hello", machinename_String: "localhost", [/size]
  port_Integer: 1234] := Module[{ostr},
  Map[Close, Complement[Streams[], Take[Streams[], 2]]] ;
  ostr = OpenWrite["!nc " <> machinename <> " " <> ToString[port]] ;
  Write[ostr, OutputForm[text]]]

If you start netcat on a remote (Mac or Linux) machine, using the Terminal, for example on a computer named "HAL9000" with:
$ nc -l -k 1234
and you execute the Mathematica command defined above, on your local machine:
wnc["Hello Hal", "HAL9000", 1234]
then "Hello Hal" appears on the remote machine. And If you type "Hello Dave" followed by carriage return, in the remote netcat session, you can retrieve this string with:
rnc["HAL9000", 1234]
The absolute timing of these transactions is milliseconds, but quite variable, and when using my flaky WiFi network, they are not 100% reliable. Since my goal here is to control a LinuxCNC process, which is in turn controlling a CNC machine, from Mathematica, these issues need attention next.  Still would like to know how to do this using pure Wolfram Language commands.
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
or Discard

Group Abstract Group Abstract