Bad request sending message to server with Sockets Java - java

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:
Usage of 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));
Missing trailing \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";
Assuming the end of the stream is reached
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";
Missing user agent
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";

Related

How can I change this code so that when you enter localhost:9080/?say=hello, it outputs hello?

I'm trying to output hello when I enter enter localhost:9080/?say=hello. But I have no idea how to do it
public class MyServer {
public static void main(String args[])throws Exception{
ServerSocket ss=new ServerSocket(9080);
Socket client = ss.accept();
Scanner in =new Scanner(client.getInputStream());
// running infinite loop for getting
// client request
while (true){
String s = in.nextLine();
if (s==null || s.trim().length()==0)
break;
System.out.println(s);
}
PrintWriter out = new PrintWriter(client.getOutputStream(),true);
String document = "<html><body>Salem</body></html>";
String response = "HTTP/1.1 200 OK\r\n" +
"Server: YarServer/2009-09-09\r\n" +
"Content-Type: text/html\r\n" +
"Content-Length: " + document.length() + "\r\n" +
"Connection: close\r\n\r\n";
out.println(response+document);
}
}
Of course this is a school work so I will not give you a ready-made working solution, just some hint.
Simplifying a lot, the HTTP protocol exchanges text strings between a client and a server. Your code already prints the strings that the browser sends to your server; take a look at the first line: it says
GET /?say=hello HTTP/1.1
"GET" is an "HTTP method", it is followed by the path of the server-side resource you requested (just a slash in this case) plus any request param (the part after the question mark) and the protocol version.
To perform a specific action for a specific path/param requested by the client, your code should examine the first line of text submitted by the browser (for example you should check for the presence of /?say=hello).
Furthermore, usuallly an HTTP server doesn't shut-down after the first request, so your code should contain another infinite loop to wait for another connection after having served the first one. Your code should also close() the client socket after you have sent the response to the browser.

BufferReader stuck in readline()

I am making an HTTP server and HTTP web client for simple Http request and response.
This is the code for Server
import java.io.*;
import java.net.*;
import java.util.*;
public final class WebServer{
public static void main(String[] args) throws Exception{
//storing port number
int port = 2048;
//open socket and wait for TCP connection
ServerSocket serverConnect = new ServerSocket(port);
System.out.println("Server started.\nListening for connections on port : " + port + " ...\n");
// we listen until user halts server execution
while (true) {
//Construct an object to process the HTTP request message.
//This will call another class where we do everything else
HttpRequest request = new HttpRequest(serverConnect.accept());
//create a new thread to process the request
Thread thread = new Thread(request);
thread.start();
} //end of while
}//end of main
}//end of the class webServer
The code for HttpRequest class is as follow:
import java.io.*;
import java.net.*;
import java.util.*;
final class HttpRequest implements Runnable{
final static String CRLF = "\r\n";
Socket socket;
//start of constructor
public HttpRequest(Socket socket) throws Exception{
this.socket=socket;
}//end of constructor
//Implement the run() method of the Runnable interface.
public void run(){
try{
processRequest();
}
catch(Exception e){
System.out.println(e);
}
}//end of run
private void processRequest() throws Exception{
//Get a reference to the scoket's input and output streams.
InputStream is = socket.getInputStream();
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
//set up the stream filters
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//Get the request line of the HTTP request message.
String requestLine = br.readLine();
//Display the request line
System.out.println();
System.out.println(requestLine);
//Get and display the header lines.
String headerLine = null;
while((headerLine = br.readLine()).length()!=0){
System.out.println(headerLine);
}
//System.out.println(requestLine);
//Extract the filename from the request line.
StringTokenizer tokens = new StringTokenizer(requestLine);
tokens.nextToken(); //skip over the method, which should be. "GET"
String fileName = tokens.nextToken();
//Prepend a "." so that file request is within the current directory
fileName = "." + fileName;
//printing for test
//System.out.println(fileName);
//Open the requested file
FileInputStream fis = null;
boolean fileExists = true;
try{
fis = new FileInputStream(fileName);
}
catch(FileNotFoundException e){
fileExists = false;
}
//Construct the response message
String statusLine = null;
String contentTypeLine = null;
String entityBody = null;
if(fileExists){
statusLine = tokens.nextToken();
contentTypeLine = "Content-type: " + contentType(fileName) + CRLF;
}
else{
statusLine = "HTTP/1.1 404 File Not Found";
contentTypeLine = "Content-type: " + "text/html" + CRLF;
entityBody = "<html><head><title>Not Found </title></head>" +
"<BODY>Not Found</body></html>";
}
//send the status line
os.writeBytes(statusLine);
//send the content Type
os.writeBytes(contentTypeLine);
//send a blank line to indicate the end of the header lines
os.writeBytes(CRLF);
//send the entity Body
if(fileExists){
sendBytes(fis, os);
fis.close();
}
else{
os.writeBytes(entityBody);
os.writeBytes(CRLF);
}
//Close scokets and streams.
fis.close();
os.close();
br.close();
socket.close();
}//end of processRequest
private static String contentType(String fileName){
if(fileName.endsWith(".htm") || fileName.endsWith(".html")){
return "text/html";
}
if(fileName.endsWith(".gif")){
return "image/gif";
}
if(fileName.endsWith(".jpeg") || fileName.endsWith(".jpg")){
return "image/jpeg";
}
return "application/octet-stream";
}// end of contentType
private static void sendBytes(FileInputStream fis, OutputStream os) throws Exception{
//Construct a 1k buffer to hold bytes on their way to the Socket
byte[] buffer = new byte[1024];
int bytes = 0;
//Copy requested file into the scoket's output stream.
while((bytes = fis.read(buffer)) != -1){
os.write(buffer, 0, bytes);
}//end of while
}//end of sendBytes
} // end of the class
The Code works fine when I make a request from Chrome webbrowser. However, I made WebClient as well. When I make request from WebClient, I am stuck as the program runs forever.
As far I have tracked, the pointer does not move from the br.readline on the while loops on the Server Side.
The code for my client is as follow.
import java.io.*;
import java.net.*;
import java.util.*;
public class WebClient{
final static String CRLF = "\r\n";
public static void main(String [] args) {
String serverName = args[0];
int port = Integer.parseInt(args[1]);
try {
// System.out.println("Connecting to " + serverName + " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to " + client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF("GET /" +args[2] +" HTTP/1.1");
out.writeUTF(CRLF);
out.writeUTF("Host: "+client.getLocalSocketAddress());
out.writeUTF(CRLF);
out.writeUTF("Connection: close" + CRLF);
out.writeUTF("User-agent: close" + CRLF);
out.writeUTF(CRLF);
//Cache-Control: max-age=0
System.out.println("Just connected to 1 ");
InputStream inFromServer = client.getInputStream();
System.out.println("Just connected to 2 ");
BufferedReader br = new BufferedReader(new InputStreamReader(inFromServer));
System.out.println("Just connected to 3 ");
String headerLine = null;
while((headerLine = br.readLine()).length()!=0){
System.out.println("asd"+headerLine);
}
System.out.println("Just connected to 4 ");
client.close();
System.out.println("Just connected to 5 ");
} catch (IOException e) {
e.printStackTrace();
}
}
}//end of the class WebClient
Can anyone help me figure out the problem.
Thanks.
First of all, you have to remove line fis.close(); (right before os.close();) in your HttpRequest class: if no file exists, this line raises NullPointerException because fis is null, so after sending Not Found response to the browser, your server does not close the socket accepted from that browser, that's why even though you see Not Found in your browser, your request never ends.
Secondly, the reason of why your client gets stuck is writeUTF() method that you used for sending request header. Seems that this line out.writeUTF(CRLF); does not really send an empty string but adds some other UTF-related character(s) (you may notice that in your server's console output), so your server gets stuck at while((headerLine = br.readLine()).length()!=0) waiting for the client to send an empty string, but never receives it. You need to replace out.writeUTF(CRLF); with out.writeBytes(CRLF);.
Also, it makes little sense to use BufferedReader for receiving binary files from socket. Reader in general is used with character-input stream, so it is not applicable for your case. You may use InputStream instead, by replacing this fragment:
String headerLine = null;
while((headerLine = br.readLine()).length()!=0){
System.out.println("asd"+headerLine);
}
with this (I chose buffer size of 4096, you may replace it with your preferred value):
int readBytes;
byte[] cbuf = new byte[4096];
while((readBytes=inFromServer.read(cbuf, 0, 4096))>-1){
System.out.println("read: " + readBytes);
}
Note: You may easily notice here that InputStream.read() will fetch not only the file itself but also statusLine, contentTypeLine and two CRLFs, so in case if you would like to separate them from the file, you may read them first, by issuing two "readLines" and then fetch the file only by read()
In your server, you use writeBytes()
Writes out the string to the underlying output stream as a sequence of bytes. Each character in the string is written out, in sequence, by discarding its high eight bits. If no exception is thrown, the counter written is incremented by the length of s.
While you may worry about non-ASCII text, generally this is what you need.
In your client you attempt to use writeUTF()
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.
While that 2-byte length in the beginning can be useful in other cases, it is not what web servers expect, including yours (and that is correct). So use writeBytes() everywhere in your client, and it will suddenly work:
out.writeBytes("GET /" +args[2] +" HTTP/1.1");
out.writeBytes(CRLF);
out.writeBytes("Host: "+client.getLocalSocketAddress());
out.writeBytes(CRLF);
out.writeBytes("Connection: close" + CRLF);
out.writeBytes("User-agent: close" + CRLF);
out.writeBytes(CRLF);
In fact those extra bytes may be visible in your server output, at least when I ran it in Eclipse, I saw garbage characters, as a combination of mysterious empty space and a tiny question mark in a rectangle (note how they also appear at the end of the lines when CRLF is sent separately):
(The first request is the one issued with writeUTF, and the second one comes from Chrome)

Java DataInputStream

Client side:
out = new DataOutputStream(connection.getOutputStream());
String process;
System.out.println("Connecting to server on "+ host + " port " + port +" at " + timestamp);
process = "Connection: "+host + ","+port+","+timestamp;
System.out.println("client len " + process.length());
out.write(process.length());
Prints:
Client len 55
Server side:
in = new DataInputStream(connection.getInputStream());
while (true) {
int len = in.readInt();
System.out.println("Length of pkt: "+len);
Prints: Length of pkt: 927166318
What's going on here? I tried writing 0 and it printed 3621743 on the server side. I checked some other sites and a few people had problems with other streams. I read about the issues arising with big vs little endianness, but I am not sure what the problem is here since I am using the data*streams that should work fine with each other.
If you call readInt() on one side, you should call writeInt(int) on the other. Change this
out.write(process.length());
to
out.writeInt(process.length());
From the Javadoc for write(int),
Writes the specified byte (the low eight bits of the argument b) to the underlying output stream.
Use out.writeInt(process.length()); instead of out.write(...); since you read an Integer from the stream afterwards.

Basic Java Webserver - Receiving a SocketException: Connection Reset

I've attempted to create a basic HTTP/1.1 compliant web server which supports simple GET requests with persistent connections. I'm getting a SocketException: Connection Reset error occuring at line 61 (if (line==null || line.equals("")). I'm testing it by running it and then directing my chrome browser to localhost portnumber. When I test it with a page with multiple images it seems like only 1 request is being processed before the exception occurs, but I'm not sure what's wrong as this is my first attempt at any kind of socket programming.
Here's my updated Code after removing DataOutputStream:
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.StringTokenizer;
public class webserve
{
public static void main(String[] args) throws Exception
{
String rootPath = "~/Documents/MockWebServerDocument/";
int port = 10000;
if(rootPath.startsWith("~" + File.separator))
{
rootPath = System.getProperty("user.home") + rootPath.substring(1);
}
String requestLine="";
StringTokenizer tokens=null;
String line, command;
Date date = new Date();
String connectionStatus="";
//Create new server socket listening on specified port number
ServerSocket serverSocket = new ServerSocket(port);
while(true)
{
//Wait for a client to connect and make a request
Socket connectionSocket = serverSocket.accept();
System.out.println("Socket opened");
//Input stream from client socket
BufferedReader incomingFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
//PrintWriter to send header to client socket
PrintWriter outgoingHeader = new PrintWriter(connectionSocket.getOutputStream(),true);
//OutputStream to send file data to client socket
ObjectOutputStream outgoingFile = new ObjectOutputStream(connectionSocket.getOutputStream());
//Date format for HTTP Header
SimpleDateFormat HTTPDateFormat = new SimpleDateFormat("EEE MMM d hh:mm:ss zzz yyyy");
//Create a HashMap to store the request header information
HashMap<String,String> requestHeader = new HashMap<String,String>();
while(connectionSocket.isConnected())
{
//requestHeader.clear();
while((line = incomingFromClient.readLine()) != null)
{
if(line.isEmpty())
{
break;
}
//If this is the first line of the request, i.e doesnt contain a colon
if(!(line.contains(":")))
{
requestLine = line;
requestHeader.put("Request", requestLine);
}
else
{
//Otherwise, find the colon in the line and create a key/value pair for the HashMap
int index = line.indexOf(':')+2;
String header = line.substring(0,index-1);
line = line.substring(index).trim();
requestHeader.put(header, line);
System.out.println(header + " " + line);
}
}
connectionStatus = (String)requestHeader.get("Connection:");
requestLine = (String)requestHeader.get("Request");
System.out.println("RequestLine: " + requestLine);
if(!requestLine.equals("")||!(requestLine.equals(null)))
{
tokens = new StringTokenizer(requestLine);
command = tokens.nextToken();
String filename = tokens.nextToken();
filename = cleanUpFilename(filename);
String fullFilepath = rootPath + filename;
System.out.println("Full FilePath: " + fullFilepath);
File file = new File(fullFilepath);
//Get the number of bytes in the file
int numOfBytes=(int)file.length();
//Open a file input stream using the full file pathname
FileInputStream inFile = new FileInputStream(fullFilepath);
//Create byte array to hold file contents
byte[] fileInBytes = new byte[numOfBytes];
inFile.read(fileInBytes,0,numOfBytes);
inFile.close();
//Write the header to the output stream
outgoingHeader.print("HTTP/1.1 200 OK\r\n");
outgoingHeader.print("Date: " + HTTPDateFormat.format(date)+"\r\n");
outgoingHeader.print("Server: BC-Server\r\n");
outgoingHeader.print("Last-Modified: " + HTTPDateFormat.format(file.lastModified())+"\r\n");
outgoingHeader.print("Connection: keep-alive\r\n");
outgoingHeader.print("Content-Length: " + numOfBytes);
outgoingHeader.print("\r\n\r\n");
//When the header has been printed, write the byte array containing the file
//to the output stream
outgoingFile.writeObject(fileInBytes);
if(!(connectionStatus.equals("keep-alive")))
{
System.out.println("Closing: " + connectionStatus);
outgoingHeader.close();
outgoingFile.close();
break;
}
else
continue;
}
}
}
}
public static String cleanUpFilename(String filename)
{
//If there is a "/" at the start of the filename, then remove it
if(filename.charAt(0) == '/')
{
filename = filename.substring(1);
}
//If we are given an absolute URI request, strip all characters
//before the third "/"
if(filename.startsWith("http://"));
{
try
{
URI httpAddress = new URI(filename);
//Get the path from the supplied absolute URI, that is remove
//all character before the third "/"
filename = httpAddress.getPath();
//Again, we may have to trim this modified address if there is an
//extra "/" at the start of the filename
if(filename.charAt(0) == '/')
{
filename = filename.substring(1);
}
}
catch (URISyntaxException e)
{
e.printStackTrace();
}
}
return filename;
}
}
Here's my error trace:
Exception in thread "main" java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:185)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:282)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:324)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:176)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:153)
at java.io.BufferedReader.readLine(BufferedReader.java:316)
at java.io.BufferedReader.readLine(BufferedReader.java:379)
at webserve.main(webserve.java:61)
Any help would be much appreciated, as I'm at a total loss.
Try testing the connection using telnet, wget or curl instead of chrome, because you can then be in control of both sided of the TCP/IP connection.
I think that your web-client is closing the connection from it's side, and you try to read from that socket again (yes, even isConnected() will throw this error when the remote party closed the connection). I am also sorry to say that there is no easy way to combat this other than to catch the exception and handle it gracefully.
This is a problem that often happens with synchronous sockets. Try using java.nio channels and selectors instead.
Using multiple output streams at the same time is highly problematic. In this case you shouldn't create the ObjectOutputStream until you are certain you are going to write an object and you have already written and flushed the headers, because ObjectOutputStream writes a header to the output, which in your present code will appear before any headers, probably causing the client to barf.
In general, SocketException: Connection Reset usually means that you have written to a connection that has already been closed by the peer. As in this case the peer is the client and the client is a Web browser, it can mean anything at all, e.g. the user stopped loading the page, he browsed away, exited the browser, closed the tab. It's not your problem. Just close the socket and forget about it.
For the same reason, your server should also set a reasonable read timeout, like say 10-30 seconds, and bail out if it fires.
The most obvious problem of your server is that it's not multi-threaded. After re-reading your description of the problem, that seems to the be root cause. You need one thread per connection. After serverSocket.accept(), create a new thread to handle the connectionSocket.
while(true)
{
//Wait for a client to connect and make a request
Socket connectionSocket = serverSocket.accept();
new Thread()
{
public void run()
{
//Input stream from client socket
BufferedReader incomingFromClient = ...
etc
}
}.start();
You cannot use DataOutputStream, it's for Java-Java communication. Try Writer for writing headers, and original OutputStream for writing file content.
What's happening is that the browser sees invalid response, and closes the connection. The serve is still writing to the client, which responds RST because the connection is gone.

Small http server using java?

I have created the following test server using java:
import java.io.*;
import java.net.*;
class tcpServer{
public static void main(String args[]){
ServerSocket s = null;
try{
s = new ServerSocket(7896);
//right now the stream is open.
while(true){
Socket clientSocket = s.accept();
Connection c = new Connection(clientSocket);
//now the connection is established
}
}catch(IOException e){
System.out.println("Unable to read: " + e.getMessage());
}
}
}
class Connection extends Thread{
Socket clientSocket;
BufferedReader din;
OutputStreamWriter outWriter;
public Connection(Socket clientSocket){
try{
this.clientSocket = clientSocket;
din = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), "ASCII"));
outWriter = new OutputStreamWriter(clientSocket.getOutputStream());
this.start();
}catch(IOException e){
System.out.println("Connection: " + e.getMessage());
}
}
public void run(){
try{
String line = null;
while((line = din.readLine())!=null){
System.out.println("Read" + line);
if(line.length()==0)
break;
}
//here write the content type etc details:
System.out.println("Someone connected: " + clientSocket);
outWriter.write("HTTP/1.1 200 OK\r\n");
outWriter.write("Date: Tue, 11 Jan 2011 13:09:20 GMT\r\n");
outWriter.write("Expires: -1\r\n");
outWriter.write("Cache-Control: private, max-age=0\r\n");
outWriter.write("Content-type: text/html\r\n");
outWriter.write("Server: vinit\r\n");
outWriter.write("X-XSS-Protection: 1; mode=block\r\n");
outWriter.write("<html><head><title>Hello</title></head><body>Hello world from my server</body></html>\r\n");
}catch(EOFException e){
System.out.println("EOF: " + e.getMessage());
}
catch(IOException e){
System.out.println("IO at run: " + e.getMessage());
}finally{
try{
outWriter.close();
clientSocket.close();
}catch(IOException e){
System.out.println("Unable to close the socket");
}
}
}
}
Now i want this server to respond to my browser. that's why i gave url: http://localhost:7896
and as a result i receive at the server side:
ReadGET / HTTP/1.1
ReadHost: localhost:7896
ReadConnection: keep-alive
ReadCache-Control: max-age=0
ReadAccept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
ReadUser-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.224 Safari/534.10
ReadAccept-Encoding: gzip,deflate,sdch
ReadAccept-Language: en-US,en;q=0.8
ReadAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
ReadCookie: test_cookie=test cookie
Read
Someone connected: Socket[addr=/0:0:0:0:0:0:0:1,port=36651,localport=7896]
And a blank white screen at my browser and source code also blank. In google chrome browser.
So can anyone please tell me where i m wrong. actually i am new to this thing. so please correct me.
Thanks in advance
You almost certainly don't want to be using DataOutputStream on the response - and writeUTF certainly isn't going to do what you want. DataOutputStream is designed for binary protocols, basically - and writeUTF writes a length-prefixed UTF-8 string, whereas HTTP just wants CRLF-terminated lines of ASCII text.
You want to write headers out a line at a time - so create an OutputStreamWriter around the socket output stream, and write to that:
writer.write("HTTP/1.1 200 OK\r\n");
writer.write("Date: Tue, 11 Jan 2011 13:09:20 GMT\r\n");
etc.
You may want to write your own writeLine method to write out a line including the CRLF at the end (don't use the system default line terminator), to make the code cleaner.
Add a blank line between the headers and the body as well, and then you should be in reasonable shape.
EDIT: Two more changes:
Firstly, you should read the request from the client. For example, change din to a BufferedReader, and initialize it like this:
din = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(),
"ASCII"));
then before you start to write the output, read the request like this:
String line;
while ((line = din.readLine()) != null) {
System.out.println("Read " + line);
if (line.length() == 0) {
break;
}
}
EDIT: As noted in comments, this wouldn't be appropriate for a full HTTP server, as it wouldn't handle binary PUT/POST data well (it may read the data into its buffer, meaning you couldn't then read it as binary data from the stream). It's fine for the test app though.
Finally, you should also either close the output writer or at least flush it - otherwise it may be buffering the data.
After making those changes, your code worked for me.
If you're interested in learning the design and development of network servers like HTTP servers in Java, you might also have a look at this repo:
https://github.com/berb/java-web-server
It's a small HTTP server in Java I started for educational purposes. Though, it shouldn't be used in production or serious use cases yet. I'm still adding new features. It currently provides multi-threading, static file handling, Basic Authentication, logging and a in-memory cache.
EDIT
An obvious error in your code is the missing \r\n between your Response Header and your HTML. Just append an additional \r\n to your last header. Additionally, you must provide the content length, unless you're using Chuncked Encoding:
String out = "<html><head><title>Hello</title></head><body>Hello world from my server</body></html>\r\n";
outWriter.write("Content-Length: "+out.getBytes().length+"\r\n\r\n");
outWriter.write(out);
The HTTP protocol is ASCII based, exept the body which depends on the Content-Type header. So, no UTF-8 headers!
Headers and body must be separated by an empty line.
Why do you set your Transfert-Encoding to chuncked? Your body is not.
Check this out, it's already done for you:
http://www.mcwalter.org/technology/java/httpd/tiny/index.html
I'm not sure if you have can use writeUTF instead, instead you may need to use writeBytes. Also, you need to terminate each line with a '\n'.

Categories