I asked a similar question in another thread but I think I'm just having trouble getting the syntax right at this point. I basically want to open a socket in Java, send a HTTP request message to get the header fields of a specific web page. My program looks like this so far:
String server = "www.w3.org";
int port = 80;
String uri = "/Protocols/rfc2616/rfc2616-sec5.html#sec5.1"
Socket socket = new Socket(server, port);
PrintStream output = new PrintStream(socket.getOutputStream());
BufferedReader socketInput = new BufferedReader(new InputStreamReader(socket.getInputStream()));
output.println("HEAD " + uri + " HTTP/1.1");
//String response = "";
String line = "";
while((line = socketInput.readLine()) != null){
System.out.println(line);
}
socketInput.close();
socket.close();
It doesn't really work. Or it doesn't work for all websites. If someone could just tell me the immediate problems with what I'm doing, that would be great. Thank you!
Change
output.println("HEAD " + uri + " HTTP/1.1");
to
output.println("HEAD " + uri + " HTTP/1.1");
output.println("Host: " + server);
output.println();
You have to send the Host header because usually there are more than one virtual host on one IP address. If you use HTTP/1.0 it works without the Host header.
I would use some higher-level component, like HttpURLConnection (see here) or apache http components.
Related
I'm trying to write a simple HTTP client that, given an absolute HTTP path, performs a simple HTTP GET request and prints out the content to standard output.
However, I'm getting the following error on any page I try to load:
java.lang.IllegalArgumentException: URI can't be null.
at sun.net.spi.DefaultProxySelector.select(DefaultProxySelector.java:141)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:926)
at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:850)
at HTTrack.main(HTTrack.java:68)
The code that is raising the exception is:
try
{
System.out.println("We will attempt to read " + getfilepath(args[0]) + " from " + getbasesite(args[0]));
URL serverConnect = new URL("http", getbasesite(args[0]), getfilepath(args[0]));
con = (HttpURLConnection)serverConnect.openConnection();
con.setRequestMethod("GET");
con.setDoOutput(true);
con.setReadTimeout(10000);
System.out.println("Attempting to connect to " + getbasesite(args[0]) + " on port 80...");
System.out.println("URL = " + con.getURL());
con.connect();
//System.out.println("Connection succeeded! Attempting to read remote file " + getfilepath(args[0]));
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line = "";
while((line = br.readLine()) != null)
{
System.out.println(line);
}
}
The line that is raising the exception (HTTrack.java:68) is the con.connect() line, and the functions getbasesite and getfilepath return the server host name and remote file paths of a URL, respectively.
For example if passed the string http://www.somesite.com/somepage.html, getbasesite will return "www.somesite.com" and getfilepath will return "/somepage.html". I know the HttpURLConnection is being passed these values correctly because when I call getURL it returns what I expect: http://www.somesite.com/somepage.html
I'm stuck as to what might be causing this error - I've tested that the HttpURLConnection class indeed gets the correct URL out of the constructor arguments with the line System.out.println("URL = " + con.getURL());, so I'm not sure why it's failing the attempts to connect with the error that the "URI can't be null".
Try removing your con.setDoOutput(true); or setting it to false. That line is telling your connection that you are going to be using it to write output, but then later on you are reading from the stream by calling con.getInputStream().
I found this code to communicate with an IRC server (see below). However I did not find how to send a command to download or upload in xdcc.
Once connected to the IRC server and positioned in the channel. I want to send a command like.
/msg bot_name xdcc send #number_of_file
Thank you in advance for your answers, examples and help.
import java.io.*;
import java.net.*;
public class HackBot {
public static void main(String[] args) throws Exception {
// The server to connect to and our details.
String server = "irc.freenode.net";
String nick = "simple_bot";
String login = "simple_bot";
// The channel which the bot will join.
String channel = "#irchacks";
// Connect directly to the IRC server.
Socket socket = new Socket(server, 6667);
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream( )));
BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream( )));
// Log on to the server.
writer.write("NICK " + nick + "\r\n");
writer.write("USER " + login + " 8 * : Java IRC Hacks Bot\r\n");
writer.flush( );
// Read lines from the server until it tells us we have connected.
String line = null;
while ((line = reader.readLine( )) != null) {
if (line.indexOf("004") >= 0) {
// We are now logged in.
break;
}
else if (line.indexOf("433") >= 0) {
System.out.println("Nickname is already in use.");
return;
}
}
// Join the channel.
writer.write("JOIN " + channel + "\r\n");
writer.flush( );
// Keep reading lines from the server.
while ((line = reader.readLine( )) != null) {
if (line.toUpperCase( ).startsWith("PING ")) {
// We must respond to PINGs to avoid being disconnected.
writer.write("PONG " + line.substring(5) + "\r\n");
writer.write("PRIVMSG " + channel + " :I got pinged!\r\n");
writer.flush( );
}
else {
// Print the raw line received by the bot.
System.out.println(line);
}
}
}
}
Your code shows only the minimum requirements needed to open a connection to a IRC server and keep it connected, actually the entire IRC protocol is much more complex and it is not implemented in the code.
The xdcc send is simply a normal IRC message sent privately to a specific other user (usually a bot) of the IRC server, therefore you can send it by using the command PRIVMSG:
writer.write("PRIVMSG " + botNickName + " :xdcc send #" + numberOfPack + "\r\n");
where botNickName and numberOfPack are two String variables containing the nickname of the bot (i.e. the recepient of the message) and the number (in string format) of the package in which you are interested.
Nevertheless you must consider that the DCC is an entire completely different protocol from the IRC protocol itself: it uses the CTCP message on IRC:
DCC SEND <filename> <ip> <port>
only to start a DCC session, but then there is the DCC protocol in order to manage the communication client-to-client. So if you really want to make the DCC works you should also implement it, but it would not be a quick job.
I need to send UPPERcased headers via http post. The first part of story was described here . Now its sockets time. :)
Socket s = new Socket(InetAddress.getByName("localhost"), 8080);
PrintWriter pw = new PrintWriter(s.getOutputStream());
// PrintStream pw = System.out;
pw.println("POST /test-servlet/TestServlet HTTP/1.0");
String params = "key1=value1&key2=value2";
pw.println("accept = text/xml");
pw.println("accept-language: ru");
pw.println("SOAPAction: requestCreditBureau");
pw.println("eif: 3");
pw.println("host: localhost");
pw.println("content-length: " + params.getBytes().length);
pw.println();
pw.println(params);
pw.println();
pw.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String t;
while((t = br.readLine()) != null) System.out.println(t);
br.close();
There are two problems here.
It doesn't work. :) The server's servlet recive:
workflow = TSM \
soapaction = requestCreditBureau
eif = 3
There is no params in HttpServletRequest on server, only headers.
The println() method will use the systems line separator to send newlines.
HTTP defines the strict usage of \r\n as the line separator.
So you should hardcode the line breaks:
pw.print("SOAPAction: requestCreditBureau\r\n");
pw.print("eif: 3\r\n");
pw.print("host: localhost\r\n");
pw.print("content-length: " + params.getBytes().length + "\r\n");
pw.print("\r\n");
Consider using java.net.HttpURLConnection instead of implementing the HTTP protocol yourself.
Thanks! The problem was that i used tomcat7. There is no such problem using jetty.
I implemented for my android application a simple HTTP Server which pass html tags with sockets and everything went as expected.
But I'm tried load in the client(browser) an simple embed image (http://localhost:1234/img.jpg\" />) and I don't know how to make the socket load it.
Can anyone help me giving the coordinates to make it?
My simple http server:
public class MainClass extends Activity {
// Called when the activity is first created
// It was called from onCreate method surrounded with try catch
[...]
ServerSocket ss = new ServerSocket(1234);
while (true) {
Socket s = ss.accept();
PrintStream out = new PrintStream(s.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
String info = null;
while ((info = in.readLine()) != null) {
System.out.println("now got " + info);
if(info.equals(""))
break;
}
out.println("HTTP/1.0 200 OK");
out.println("MIME_version:1.0");
out.println("Content_Type:text/html");
String c = "<html>" +
"<head></head>" +
"<body>" +
"<img src=\"http://localhost:1234/img.jpg\" />" + // << Does not load in the browser
"<h1> hi </h1>" +
"</body>" +
"</html>";
out.println("Content_Length:" + c.length());
out.println("");
out.println(c);
out.close();
s.close();
in.close();
}
[...]
}
}
Thanks in advance!
The reason why the image is not loading is because the file http://localhost:1234/img.jpg is not being served by your application. When an <img /> tag is processed, the browser will go out to the src path and load that file into the page.
I don't know how to implement that offhand (I have not implemented HTTP before). But you would at least have to process the inputed GET request, and differentiate between the base webpage and the image request.
Working on a HTTP client program using Netbeans.
So far I have gotten to here in my HttpClient class:
public class MyHttpClient {
MyHttpRequest request;
String host;
public MyHttpResponse execute(MyHttpRequest request) throws IOException {
//Creating the response object
MyHttpResponse response = new MyHttpResponse();
//Get web server host and port from request.
String host = request.getHost();
int port = request.getPort();
//Check 1: HOST AND PORT NAME CORRECT!
System.out.println("host: " + host + " port: " + String.valueOf(port));
//Get resource path on web server from requests.
String path = request.getPath();
//Check 2: ENSURE PATH IS CORRECT!
System.out.println("path: " + path);
//Open connection to the web server
Socket s = new Socket(host, port);
//Get Socket input stream and wrap it in Buffered Reader so it can be read line by line.
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(s.getInputStream()));
//Get Socket output stream and wrap it in a DataOutputStream so it can be written to line by line.
DataOutputStream outToServer = new DataOutputStream(s.getOutputStream());
//Get request method
String method = request.getMethod();
//Check 3: ENSURE REQUEST IS CORRECT GET/POST!
System.out.println("Method: " + method);
//GET REQUEST
if(method.equalsIgnoreCase("GET")){
//Send request to server
outToServer.writeChars("GET " + path + " HTTP/1.0");
//HTTP RESPONSE
System.out.println("WAITING FOR RESPONSE!");
String line = inFromServer.readLine();
System.out.println("Line: " + line);
}
//Returning the response
return response;
}
}
I have checked to ensure my request line is constructed correctly, as seen in the print statements throughout. However when I get to this line the program hangs:
System.out.println("WAITING FOR RESPONSE!");
String line = inFromServer.readLine();
I have no idea why... My server is localhost WAMP. It is up and running correctly. I have the file I am requesting stored on the localhost. I can access it through browser.
Any ideas what might be going wrong??
No CR or LF is one of your problems. You should be writing ASCII characters and may be a Host header.
outToServer.write(("GET " + path + " HTTP/1.0\r\n").getBytes("ASCII"));
outToServer.write("Host: myhost.com\r\n\r\n".getBytes("ASCII"));
outToServer.flush();