NetCat is a very simple and useful tool, which allows to see contents of TCP/IP requests, like HTTP etc., both server and client side. With NetCat it is possible to either set up TCP/IP listener on a port and receive data or send TCP/IP request to remote server.
The code and executable for Java version of NetCat is available on GitHub:
http://github.com/rafalrusin/netcat/downloads
I used Jakarta Commons CLI to handle commandline parameters. The code is as simple as that:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static void main(String[] args) throws Exception { | |
CommandLineParser parser = new PosixParser(); | |
Options options = new Options(); | |
options.addOption("l", "listen", false, "listen mode"); | |
options.addOption("p", "port", true, "port number"); | |
CommandLine line = parser.parse(options, args); | |
if (line.hasOption('l')) { | |
if (line.hasOption('p')) { | |
int port = Integer.parseInt(line.getOptionValue('p')); | |
listen(port); | |
} | |
} else { | |
if (line.hasOption('p')) { | |
int port = Integer.parseInt(line.getOptionValue('p')); | |
connect(line.getArgs()[0], port); | |
} else { | |
HelpFormatter formatter = new HelpFormatter(); | |
formatter.printHelp("netcat [OPTIONS] <HOST>", options); | |
} | |
} | |
} |
In order to handle stream I/O I implemented a simple StreamTransferer class like this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class StreamTransferer implements Runnable { | |
private InputStream input; | |
private OutputStream output; | |
public StreamTransferer(InputStream input, OutputStream output) { | |
this.input = input; | |
this.output = output; | |
} | |
@Override | |
public void run() { | |
try { | |
PrintWriter writer = new PrintWriter(output); | |
BufferedReader reader = new BufferedReader(new InputStreamReader(input)); | |
String line; | |
while ((line = reader.readLine()) != null) { | |
writer.println(line); | |
writer.flush(); | |
} | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
} |
The only issue I had was that whenever I closed Java I/O stream using OutputStream.close(), it was closing the whole socket. So I couldn't receive any response back from server. So instead of doing that I had to use Socket shutdownOutput method, like in the code below.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private static void transferStreams(Socket socket) throws IOException, | |
InterruptedException { | |
InputStream input1 = System.in; | |
OutputStream output1 = socket.getOutputStream(); | |
InputStream input2 = socket.getInputStream(); | |
PrintStream output2 = System.out; | |
Thread thread1 = new Thread(new StreamTransferer(input1, output1)); | |
Thread thread2 = new Thread(new StreamTransferer(input2, output2)); | |
thread1.start(); | |
thread2.start(); | |
thread1.join(); | |
socket.shutdownOutput(); | |
thread2.join(); | |
} |
It worked perfectly then.
So it is possible to send HTTP GET requests to google using this tool. In order to do that, you need to connect to google.com and type GET and enter. CTRL+Z and enter is for closing input stream under Windows. CTRL+D is for Linux. The example looks like below:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ java -jar netcat.jar google.com -p 80 | |
Connecting to google.com port 80 | |
GET | |
HTTP/1.0 302 Found | |
Location: http://www.google.pl/ | |
Cache-Control: private | |
Content-Type: text/html; charset=UTF-8 | |
Set-Cookie: PREF=ID=d3ab73f155cad978:FF=0:TM=1337454744:LM=1337454744:S=q7r3IZqRmvlnVqwn; expires=Mon, 19-May-2014 19:12:24 GMT; path=/; domain=.google.com | |
Set-Cookie: NID=59=j3omC2VT9csLVOvUOZdmom-YTRVeXXWUEc6FoMnUrMh_4HBFS1MStyT5tN4rzC1846-wmuXros8ZFYUPyBIP5l9kwF6z4nMtyNmXmGhByd15Zrlhwj-NxNmeuu9mrbJU; expires=Sun | |
, 18-Nov-2012 19:12:24 GMT; path=/; domain=.google.com; HttpOnly | |
P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info." | |
Date: Sat, 19 May 2012 19:12:24 GMT | |
Server: gws | |
Content-Length: 218 | |
X-XSS-Protection: 1; mode=block | |
X-Frame-Options: SAMEORIGIN | |
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8"> | |
<TITLE>302 Moved</TITLE></HEAD><BODY> | |
<H1>302 Moved</H1> | |
The document has moved | |
<A HREF="http://www.google.pl/">here</A>. | |
</BODY></HTML> | |
^Z |