I'm trying to open a socket, send a message (requesting the HEAD) and get the response from server.
My code is similar to a lot of other codes I'm looking for, here in SO,or googling.
Here is:
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;
public class ClientTCPSocket {
public static final int PORT = 80;
public static void main(String argv[]) {
BufferedReader inputKeyboard = new BufferedReader(new InputStreamReader(System.in));
Socket socket;
InetAddress ipAddress;
String host = "";
String head = "";
String input_message = "";
try {
System.out.println("Host to connect?");
host = inputKeyboard.readLine();
head = "HEAD / HTTP/1.1\r\n"
+ "Host: "+ host +"\r\n"
+ "\r";
ipAddress = InetAddress.getByName(host);
socket = new Socket(ipAddress, PORT);
DataOutputStream ouput = new DataOutputStream(socket.getOutputStream());
System.out.println("\nSending info...");
System.out.println(head);
System.out.println("===============================");
ouput.writeUTF(head);
BufferedReader inputFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while ((input_message = inputFromServer.readLine()) != null) {
System.out.println(input_message);
}
System.out.println("===============================");
socket.close();
inputFromServer.close();
} catch (IOException e) {
System.out.println("Alguna cosa ha anat malament");
e.printStackTrace();
}
}
}
(As I read in wiki: https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Message_format I need to put the carriage and line feed. I said that because I tested only using "\n")
But after all, If I call for example "localhost" (I got a basic xampp opened in the mac) or even "google.com", I'm getting Error 400, BAD Request
, when is supposed I had to receive code 200.
I don't know what I'm forgetting or which combination of info I have to send .
Your problems are caused by multiple reasons:
writeUTF
From the documentation of ouput.writeUTF(head);
Writes a string to the underlying output stream using modified UTF-8 encoding in a machine-independent manner. First, two bytes are written to the output stream as if by the writeShort method giving the number of bytes to follow. This value is the number of bytes actually written out, not the length of the string. Following the length, each character of the string is output, in sequence, using the modified UTF-8 encoding for the character. If no exception is thrown, the counter written is incremented by the total number of bytes written to the output stream. This will be at least two plus the length of str, and at most two plus thrice the length of str.
Since these 2 bytes are prefixed to your string, it is causing an invalid HTTP request
You should manually convert your string to bytes, and send that, or use an InputStreamWriter
ouput.write(head.getBytes(StandardCharsets.UTF_8));
\n
Your final newline in the message is incomplete
head = "HEAD / HTTP/1.1\r\n" + "Host: "+ host +"\r\n" + "\r";
should be
head = "HEAD / HTTP/1.1\r\n"
+ "Host: "+ host +"\r\n"
+ "\r\n";
In HTTP 1.1, all connections are persistent by default, this means that the server will keep the connection open for a while after a request.
WHile you don't see the effect at the moment (because the malformed request, the server assumes its HTTP 1.0), this is a problem if you start sending valid requests.
Since this means that your program never breaks out of the for loop, we need to either detect the end of a request (hard!), or be a little less efficient and say to the server that we want to close our connection:
head = "HEAD / HTTP/1.1\r\n"
+ "Host: "+ host +"\r\n"
+ "Connection: close\r\n"
+ "\r\n";
While this isn't a violation of the protocol persee, some server may require the user agent header these days, and reject all connections without this header.
This is really easy.
head = "HEAD / HTTP/1.1\r\n"
+ "Host: "+ host +"\r\n"
+ "user-agent: Test program made by https://stackoverflow.com/users/1282166/shudy\r\n"
+ "\r\n";