error in my java code for a web server - java

I keep getting these error and i have no clue why. I've been working on this for over 4 hours and i still cant fix this error. i honestly don't know what i'm doing wrong here.
WebServer.java:84: error: class, interface, or enum expected
StringTokenizer tokens = new StringTokenizer(requestLine);
^
WebServer.java:85: error: class, interface, or enum expected
tokens.nextToken(); // skip over the method, which should be "GET"
^
WebServer.java:86: error: class, interface, or enum expected
String fileName = tokens.nextToken();
^
WebServer.java:89: error: class, interface, or enum expected
fileName = "." + fileName;
^
WebServer.java:92: error: class, interface, or enum expected
FileInputStream fis = null;
^
WebServer.java:93: error: class, interface, or enum expected
boolean fileExists = true;
^
WebServer.java:94: error: class, interface, or enum expected
try {
^
WebServer.java:96: error: class, interface, or enum expected
} catch (FileNotFoundException e) {
^
WebServer.java:98: error: class, interface, or enum expected
}
^
WebServer.java:102: error: class, interface, or enum expected
String contentTypeLine = null;
^
WebServer.java:103: error: class, interface, or enum expected
String entityBody = null;
^
WebServer.java:104: error: class, interface, or enum expected
if (fileExists) {
^
WebServer.java:106: error: class, interface, or enum expected
contentTypeLine = "Content-type: " + contentType( fileName ) + CRL
^
WebServer.java:107: error: class, interface, or enum expected
}
^
WebServer.java:110: error: class, interface, or enum expected
contentTypeLine = "Content-type: " + "text/html" + CRLF;
^
WebServer.java:111: error: class, interface, or enum expected
entityBody = "<HTML>" +
^
WebServer.java:114: error: class, interface, or enum expected
}
^
WebServer.java:119: error: class, interface, or enum expected
os.writeBytes(contentTypeLine);
^
WebServer.java:121: error: class, interface, or enum expected
os.writeBytes(CRLF);
^
WebServer.java:123: error: class, interface, or enum expected
if (fileExists) {
^
WebServer.java:125: error: class, interface, or enum expected
fis.close();
^
WebServer.java:126: error: class, interface, or enum expected
}
^
WebServer.java:129: error: class, interface, or enum expected
}
^
WebServer.java:136: error: class, interface, or enum expected
int bytes = 0;
^
WebServer.java:138: error: class, interface, or enum expected
while((bytes = fis.read(buffer)) != -1 ) {
^
WebServer.java:140: error: class, interface, or enum expected
}
^
WebServer.java:147: error: class, interface, or enum expected
}
^
WebServer.java:150: error: class, interface, or enum expected
}
^
WebServer.java:153: error: class, interface, or enum expected
}
^
WebServer.java:156: error: class, interface, or enum expected
}
^
WebServer.java:159: error: class, interface, or enum expected
}
^
WebServer.java:161: error: class, interface, or enum expected
}
^
32 errors
here is source code
import java.io.* ;
import java.net.* ;
import java.util.* ;
public final class WebServer{
public static void main(String argv[]) throws Exception
{
// Set the port number.
int port = 6789;
// Establish the listen socket.
ServerSocket listenSocket = new ServerSocket(port);
//Process HTTP service requests in an infinite loop
while (true) {
// Listen for a TCP connection request
Socket connectionSocket = listenSocket.accept();
// Construct an object to process the HTTP request message
HttpRequest request = new HttpRequest(connectionSocket);
// Create a new thread to process the request.
Thread thread = new Thread(request);
// Start the thread.
thread.start();
}
}
}
final class HttpRequest implements Runnable
{
final static String CRLF = "\r\n";
Socket socket;
// Constructor
public HttpRequest(Socket socket) throws Exception
{
this.socket = socket;
}
// Implement the run() method of the Runnable interface.
public void run()
{
try
{
processRequest();
}
catch (Exception e)
{
System.out.println(e);
}
}
private void processRequest() throws Exception
{
// Get a reference to the socket's input and output streams.
InputStream is = socket.getInputStream();
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
// Set up input 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);
}
// Close streams and socket.
os.close();
br.close();
socket.close();
}
}
// 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;
// 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 = "HTTP/1.0 200 OK" + CRLF;
contentTypeLine = "Content-type: " + contentType( fileName ) + CRLF;
}
else {
statusLine = "HTTP/1.0 404 Not Found" + CRLF;
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 line.
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);
}
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 socket's output stream.
while((bytes = fis.read(buffer)) != -1 ) {
os.write(buffer, 0, bytes);
}
}
private static String contentType(String fileName)
{
if (fileName.endsWith(".htm") || fileName.endsWith(".html")) {
return "text/html";
}
if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
return "image/jpeg";
}
if (fileName.endsWith(".gif")) {
return "image/gif";
}
if (fileName.endsWith(".txt")) {
return "text/plain";
}
if (fileName.endsWith(".pdf")) {
return "application/pdf";
}
return "application/octet-stream";
}
can someone please help me under what is wrong with my code. I would greatly appreciate the help.

can someone please help me under what is wrong with my code.
Starting from the comment line
// Extract the filename from the request line.
you have a bunch of statements, and then method declarations that are not inside any class. That is not legal Java.
If they are supposed to be inside a class (e.g. your HttpRequest class or WebServer class) then you have probably made a mistake with opening / closing brackets further up the file.
If not ... then you misunderstand Java. All executable code in Java must be declared inside a class (or interface or enum).

You are misplacing some braces.
import java.io.*;
import java.net.*;
import java.util.*;
public final class WebServer {
public static void main(String argv[]) throws Exception {
// Set the port number.
int port = 6789;
// Establish the listen socket.
ServerSocket listenSocket = new ServerSocket(port);
// Process HTTP service requests in an infinite loop
while (true) {
// Listen for a TCP connection request
Socket connectionSocket = listenSocket.accept();
// Construct an object to process the HTTP request message
HttpRequest request = new HttpRequest(connectionSocket);
// Create a new thread to process the request.
Thread thread = new Thread(request);
// Start the thread.
thread.start();
}
}
}
final class HttpRequest implements Runnable {
final static String CRLF = "\r\n";
Socket socket;
// Constructor
public HttpRequest(Socket socket) throws Exception {
this.socket = socket;
}
// Implement the run() method of the Runnable interface.
public void run() {
try {
processRequest();
} catch (Exception e) {
System.out.println(e);
}
}
private void processRequest() throws Exception {
// Get a reference to the socket's input and output streams.
InputStream is = socket.getInputStream();
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
// Set up input 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);
}
// Close streams and socket.
os.close();
br.close();
socket.close();
// } // *** DELETED
// } // *** DELETED
// 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;
// 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 = "HTTP/1.0 200 OK" + CRLF;
contentTypeLine = "Content-type: " + contentType(fileName) + CRLF;
} else {
statusLine = "HTTP/1.0 404 Not Found" + CRLF;
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 line.
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);
}
} // *** INSERTED
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 socket's output stream.
while ((bytes = fis.read(buffer)) != -1) {
os.write(buffer, 0, bytes);
}
}
private static String contentType(String fileName) {
if (fileName.endsWith(".htm") || fileName.endsWith(".html")) {
return "text/html";
}
if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
return "image/jpeg";
}
if (fileName.endsWith(".gif")) {
return "image/gif";
}
if (fileName.endsWith(".txt")) {
return "text/plain";
}
if (fileName.endsWith(".pdf")) {
return "application/pdf";
}
return "application/octet-stream";
}
} // *** INSERTED

Related

Java custom class loader issue

I'm sending a Class object from client to server side. Every time the server needs to load the Class object sent by the client instead of reusing it by parent delegation model (when it was loaded during the 1st iteration).
I'm trying to use a custom class loader on the server side whose loadClass(String) simply calls findClass() instead of checking with parent hierarchy.
To achieve this, I'm doing following:
Generate byte[] by reading the .class file on the client side as following:
Class cl = com.example.XYZ.class;
String path = cl.getName().replace('.', '/') + ".class";
InputStream is = cl.getClassLoader().getResourceAsStream(path);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int data = -1;
while((data=is.read())!=-1)
bos.write(data);
byte[] classBinaryData = bos.toByteArray();
I'm sending classBinaryData to the server side.
On the server side, every time I retrieve the byte[], verify if it's the same as on client side by matching MD5 checksum, then I create a new instance of my custom class loader and pass the byte array so it could be used in calling defineClass from within findClass.
However, I'm getting either of the errors (depending on the way I create byte[] out of .class)
Incompatible magic value ..... in class file <Unknown>
OR
com/example/XYZ (wrong name: com/example/XYZ) coming from defineClass
I need help in figuring out the mistake in my approach/code.
Your byte[] generation code looks fine.
When I used the byte array generated form your code to load the class with following class loader code, it was able to load the class successfully.
class CustomClassLoader extends ClassLoader {
public Class loadTheClass(String name, byte[] bytes) {
return defineClass(name, bytes, 0, bytes.length);
}
}
Using this classloader like this
CustomClassLoader ccl = new CustomClassLoader();
Class cz = ccl.loadTheClass("com.example.XYZ", classBinaryData);
Object o = cz.newInstance();
I think you must use '.' instead of '/' in the name when you are loading the class at server side.
And ensure that the byte array data is not changed in your other code.
Your code looks fine. Your error is somewhere else.
You are, in some way, returning bad class files from your class loader.
The first error means the byte array is totally garbled; the first 4 bytes are wrong. You can check them easily (they have to be 0xCAFEBABE), to catch this error earlier.
The other error, I think, means that you are returning the definition of a different class than was requested.
1. Missing Dot Notation
com/example/XYZ (wrong name: com/example/XYZ) coming from defineClass
You should be using dot notation, i.e., com.example.XYZ
Class clazz = classLoader.loadCustomClass("com.example.XYZ", bytes);
2. Invalid Magic Number (Corrupt Class Bytes)
Incompatible magic value ..... in class file
You are getting the above error because the start of the class byte array is corrupted. It's complaining about Incompatible magic value by throwing a java.lang.ClassFormatError. It usually happens when the class loader doesn't find 0xCAFEBABE (magic number) at the beginning of the class bytes.
Here is a simple example by which you can recreate the error.
In this example, the com.basaki.model.Book class file is saved as a Base64 encoded string.
The method testLoadingClassWithCorrectMagicNumber tries to load the class from the Base64 encoded string after decoding it to a byte array. It loads normally without any incident.
In method testLoadingClassWithIncorrectCorrectMagicNumber, the byte array (after the Base64 string is decoded) is corrupted by replacing the first character from c to b. Now instead of the magic number being 0xCAFEBABE, it is 0xBAFEBABE. The class loader now throws the following exception while trying to load the corrupt binary array,
java.lang.ClassFormatError: Incompatible magic value 3137256126 in class file com/basaki/model/Book
public class LoadingBookFromBinaryArrayTest {
private static class MyCustomClassLoader extends ClassLoader {
public Class loadCustomClass(String name, byte[] bytes) {
return defineClass(name, bytes, 0, bytes.length);
}
}
public static String BOOK_CLAZZ = "yv66vgAAADQAHQoABQAYCQAEABkJAAQAGgcAGwcAHAEABXRpdGxlAQASTGphdmEvbGFuZy9TdHJpbmc7AQAGYXV0aG9yAQAGPGluaXQ-AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABdMY29tL2Jhc2FraS9tb2RlbC9Cb29rOwEACGdldFRpdGxlAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAAhzZXRUaXRsZQEAFShMamF2YS9sYW5nL1N0cmluZzspVgEACWdldEF1dGhvcgEACXNldEF1dGhvcgEAClNvdXJjZUZpbGUBAAlCb29rLmphdmEMAAkACgwABgAHDAAIAAcBABVjb20vYmFzYWtpL21vZGVsL0Jvb2sBABBqYXZhL2xhbmcvT2JqZWN0ACEABAAFAAAAAgACAAYABwAAAAIACAAHAAAABQABAAkACgABAAsAAAAvAAEAAQAAAAUqtwABsQAAAAIADAAAAAYAAQAAAAMADQAAAAwAAQAAAAUADgAPAAAAAQAQABEAAQALAAAALwABAAEAAAAFKrQAArAAAAACAAwAAAAGAAEAAAAJAA0AAAAMAAEAAAAFAA4ADwAAAAEAEgATAAEACwAAAD4AAgACAAAABiortQACsQAAAAIADAAAAAoAAgAAAA0ABQAOAA0AAAAWAAIAAAAGAA4ADwAAAAAABgAGAAcAAQABABQAEQABAAsAAAAvAAEAAQAAAAUqtAADsAAAAAIADAAAAAYAAQAAABEADQAAAAwAAQAAAAUADgAPAAAAAQAVABMAAQALAAAAPgACAAIAAAAGKiu1AAOxAAAAAgAMAAAACgACAAAAFQAFABYADQAAABYAAgAAAAYADgAPAAAAAAAGAAgABwABAAEAFgAAAAIAFw==";
#Test
public void testLoadingClassWithCorrectMagicNumber() throws IllegalAccessException, InstantiationException, DecoderException {
byte[] bytes = Base64.getUrlDecoder().decode(BOOK_CLAZZ);
MyCustomClassLoader classLoader = new MyCustomClassLoader();
Class clazz = classLoader.loadCustomClass("com.basaki.model.Book", bytes);
}
#Test(expected = ClassFormatError.class)
public void testLoadingClassWithIncorrectCorrectMagicNumber() throws IllegalAccessException, InstantiationException, DecoderException {
byte[] bytes = Base64.getUrlDecoder().decode(BOOK_CLAZZ);
String hex = Hex.encodeHexString(bytes);
System.out.println(hex);
// changing magic number 0xCAFEBABE to invalid 0xBAFEBABE
String malHex = "b" + hex.substring(1, hex.length());
System.out.println(malHex);
byte[] malBytes = Hex.decodeHex(malHex.toCharArray());
MyCustomClassLoader classLoader = new MyCustomClassLoader();
Class clazz = classLoader.loadCustomClass("com.basaki.model.Book", bytes9);
}
}
As has been stated above the issue seems to be somewhere else besides the gathering of the byte array. It is possible that the bytes are not being processed properly on the server side. I've created a fairly simple example that is similar to what you are doing but it shows how I send and receive the class byte array.
package org.valhalla.classloader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class RemoteClassLoader extends ClassLoader {
private Socket socket;
private DataOutputStream dos;
private DataInputStream dis;
public RemoteClassLoader(Socket socket, ClassLoader parent) {
super(parent);
this.socket = socket;
OutputStream os;
InputStream is;
try {
os = socket.getOutputStream();
is = socket.getInputStream();
} catch (IOException e) {
throw new RuntimeException("Unable to get Socket output stream", e);
}
dos = new DataOutputStream(os);
dis = new DataInputStream(is);
}
#Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
Class<?> clz = null;
System.out.println("Looking up class: " + name);
synchronized(this.getClassLoadingLock(name)) {
try {
System.out.println("Sending request for class: " + name);
dos.writeUTF(name);
boolean success = dis.readBoolean();
System.out.println("Action was " + success);
if (success) {
// Get bytes;
System.out.println("Reading size of class file");
int len = dis.readInt();
System.out.println("Size of class is " + len);
byte data[] = new byte[len];
int cur, size = 0;
for (cur = 0 ; cur < len ; cur += size) {
size = dis.read(data, cur, len - cur);
System.out.println("Read size: " + size);
}
System.out.println("Completed reading class file for class " + name);
return defineClass(name, data, 0, len);
}
} catch (IOException e) {
throw new ClassNotFoundException("Class: " + name + " was not found", e);
}
}
return clz;
}
public void close() {
try {
if (socket != null && socket.isClosed() == false) {
this.socket.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
This class will read the byte array and load it within the server side of the code. Note that I use a simple protocol to determine how many bytes are being sent over the wire and insure that I have read the correct amount of bytes.
Here is the client side code that will send the information over the wire. It is an extension of what you mentioned above.
package org.valhalla.client;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.net.Socket;
public class ClientConnection {
private Socket socket;
public ClientConnection(Socket socket) {
this.socket = socket;
}
public void process() {
try {
DataInputStream dis = new DataInputStream(socket.getInputStream());
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
String name = null;
while ((name = dis.readUTF()) != null && name.length() > 0) {
System.out.println("Looking up class: " + name);
InputStream resource = ClassLoader.getSystemResourceAsStream(name.replace('.', '/') + ".class");
if (resource == null) {
System.out.println("Class not found: " + name);
dos.writeBoolean(false);
continue;
}
System.out.println("Found class: " + name);
try {
byte buf[] = new byte[1024];
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int size = 0;
while ((size = resource.read(buf)) > 0) {
bos.write(buf, 0, size);
}
byte clz[] = bos.toByteArray();
dos.writeBoolean(true);
System.out.println("Sendding class size: " + clz.length);
dos.writeInt(clz.length);
System.out.println("Sending class bytes");
dos.write(clz);
System.out.println("Sent class bytes");
} catch (Throwable t) {
t.printStackTrace();
dos.writeBoolean(false);
}
}
} catch (Throwable t) {
t.printStackTrace();
} finally {
if (socket != null && socket.isClosed() == false) {
try { socket.close(); } catch(Throwable t) {}
}
}
}
}
As you see it just sends some information to the server that lets it know how much data is expected to be transferred. The following classes can be used with the above classes to show how this works.
package org.valhalla.classloader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
public class RemoteClassLoaderServer {
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("syntax error: missing port");
System.exit(1);
}
int port = 0;
try {
port = Integer.parseInt(args[0]);
} catch(NumberFormatException nfe) {
System.out.println("Invalid port number: " + args[1]);
System.exit(2);
}
if (port < 0) {
System.out.println("Port cannot be negative: " + port);
}
ServerSocket server = null;
try {
server = new ServerSocket(port);
} catch (IOException e) {
System.out.println("Unable to create server socket for port: " + port);
System.exit(3);
}
Socket s = null;
try {
s = server.accept();
InputStream is = s.getInputStream();
DataInputStream dis = new DataInputStream(is);
System.out.println("Waiting for class name");
String name = dis.readUTF();
System.out.println("Received class name: " + name);
RemoteClassLoader rcl = new RemoteClassLoader(s, RemoteClassLoaderServer.class.getClassLoader());
System.out.println("Finding class: " + name);
Class<?> clz = rcl.loadClass(name);
Method m = clz.getMethod("main", String[].class);
System.out.println("Executing main method");
m.invoke(null, new Object[] { new String[0] });
System.out.println("done");
new DataOutputStream(s.getOutputStream()).writeUTF("");
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (s != null && s.isClosed() == false) {
try { s.close(); } catch(Throwable t) {}
}
}
}
}
Here are the client side classes
package org.valhalla.client;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class ClientMain {
public static void main(String[] args) {
int port = Integer.parseInt(args[0]);
try {
Socket socket = new Socket("localhost", port);
System.out.println("Opened socket at port: " + port);
String name = Main.class.getName();
new DataOutputStream(socket.getOutputStream()).writeUTF(name);
System.out.println("Sent Class name: " + name);
ClientConnection conn = new ClientConnection(socket);
conn.process();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
This class will be run within the server side.
package org.valhalla.client;
public class Main {
public static void main(String args[]) {
Client client = new Client();
client.execute();
}
}
with this class.
package org.valhalla.client;
public class Client {
public void execute() {
System.out.println("######### We are calling the Client class execute method #####");
}
}
Hope this helps.

map file directory from a java server to local machine

I have created a java server application which will take GET requests and return files to the browser. Also the files are downloaded to the directory using "content-disposition:attachment" in header.But this only downloads as files, I want to download as a folder and map it to a local directory. for example
localhost:8080/xyz.jpg gives u an image .But localhost:8080/src/xyz.jpg should be downlaoded as src folder with an image in it eg: downloads/src/xyz.jpg. Currently if i do that ,it downloads as just a file. Since you guys asked.Here is the example code i used :) .thanks
import java.io.*;
import java.net.*;
import java.util.*;
public class myHTTPServer extends Thread {
static final String HTML_START =
"<html>" +
"<title>HTTP Server in java</title>" +
"<body>";
static final String HTML_END =
"</body>" +
"</html>";
Socket connectedClient = null;
BufferedReader inFromClient = null;
DataOutputStream outToClient = null;
public myHTTPServer(Socket client) {
connectedClient = client;
}
public void run() {
try {
System.out.println( "The Client "+
connectedClient.getInetAddress() + ":" + connectedClient.getPort() + " is connected");
inFromClient = new BufferedReader(new InputStreamReader (connectedClient.getInputStream()));
outToClient = new DataOutputStream(connectedClient.getOutputStream());
String requestString = inFromClient.readLine();
String headerLine = requestString;
StringTokenizer tokenizer = new StringTokenizer(headerLine);
String httpMethod = tokenizer.nextToken();
String httpQueryString = tokenizer.nextToken();
StringBuffer responseBuffer = new StringBuffer();
responseBuffer.append("<b> This is the HTTP Server Home Page.... </b><BR>");
responseBuffer.append("The HTTP Client request is ....<BR>");
System.out.println("The HTTP request string is ....");
while (inFromClient.ready())
{
// Read the HTTP complete HTTP Query
responseBuffer.append(requestString + "<BR>");
System.out.println(requestString);
requestString = inFromClient.readLine();
}
if (httpMethod.equals("GET")) {
if (httpQueryString.equals("/")) {
// The default home page
sendResponse(200, responseBuffer.toString(), false);
} else {
//This is interpreted as a file name
String fileName = httpQueryString.replaceFirst("/", "");
fileName = URLDecoder.decode(fileName);
if (new File(fileName).isFile()){
sendResponse(200, fileName, true);
}
else {
sendResponse(404, "<b>The Requested resource not found ...." +
"Usage: http://127.0.0.1:5000 or http://127.0.0.1:5000/</b>", false);
}
}
}
else sendResponse(404, "<b>The Requested resource not found ...." +
"Usage: http://127.0.0.1:5000 or http://127.0.0.1:5000/</b>", false);
} catch (Exception e) {
e.printStackTrace();
}
}
public void sendResponse (int statusCode, String responseString, boolean isFile) throws Exception {
String statusLine = null;
String serverdetails = "Server: Java HTTPServer";
String contentLengthLine = null;
String fileName = null;
String contentTypeLine = "Content-Type: text/html" + "\r\n";
String Content_disposition="Content-Disposition: attachment; filename='src/fname.ext'";
FileInputStream fin = null;
if (statusCode == 200)
statusLine = "HTTP/1.1 200 OK" + "\r\n";
else
statusLine = "HTTP/1.1 404 Not Found" + "\r\n";
if (isFile) {
fileName = responseString;
fin = new FileInputStream(fileName);
contentLengthLine = "Content-Length: " + Integer.toString(fin.available()) + "\r\n";
if (!fileName.endsWith(".htm") && !fileName.endsWith(".html"))
contentTypeLine = "Content-Type: \r\n";
}
else {
responseString = myHTTPServer.HTML_START + responseString + myHTTPServer.HTML_END;
contentLengthLine = "Content-Length: " + responseString.length() + "\r\n";
}
outToClient.writeBytes(statusLine);
outToClient.writeBytes(serverdetails);
outToClient.writeBytes(contentTypeLine);
outToClient.writeBytes(contentLengthLine);
outToClient.writeBytes(Content_disposition);
outToClient.writeBytes("Connection: close\r\n");
outToClient.writeBytes("\r\n");
if (isFile) sendFile(fin, outToClient);
else outToClient.writeBytes(responseString);
outToClient.close();
}
public void sendFile (FileInputStream fin, DataOutputStream out) throws Exception {
byte[] buffer = new byte[1024] ;
int bytesRead;
while ((bytesRead = fin.read(buffer)) != -1 ) {
out.write(buffer, 0, bytesRead);
}
fin.close();
}
public static void main (String args[]) throws Exception {
ServerSocket Server = new ServerSocket (5000, 10, InetAddress.getByName("127.0.0.1"));
System.out.println ("TCPServer Waiting for client on port 5000");
while(true) {
Socket connected = Server.accept();
(new myHTTPServer(connected)).start();
}
}
}
You can't do this using the HTTP protocol and a normal browser, there is no MIME type for folders. Your browser is able to download only files.
If you want to do this through HTTP:
Option 1: Generate a "zip" file (or some other format that enables you to package a folder tree into a single file) which contains the folder tree and send that to the browser.
Option 2: Develop a custom client program that is able to interpret the response that it gets from the server and create the corresponding folders on the local filesystem.

Java TCP Simple Webserver Problems with response codes (homework)

This is an assignment for a course we are having and i need some help.
I am having problems for example, trying to request a file that does not exist, it works that a 404 file not found page comes up, but when i look in the web tool for Safari i can see that the response code is 200, OK, which is definialty wrong, it should be the code that is the error.
But why i don't see, i send the error code header when a error occurs, but it´still doesn't work. Can somebody point me at the right direction or maybe just say what the problem is and i can fix it :D ?
Main:
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
public class WebServer {
private static int PORT = 8888;
private static String ROOT_DIR = "";
public static void main(String[] args) {
if (isCorrect(args) == true) {
boolean isRunning = true;
try {
/* Creates a new server socket */
ServerSocket serverSocket = new ServerSocket();
/* Binds the port to the server */
SocketAddress localBindPoint = new InetSocketAddress(PORT);
serverSocket.bind(localBindPoint);
System.out.println("==============================================" +
"\n| HTTP Web Server |" +
"\n===================" +
"\n| Configuration: " +
"\n| Directory: " +
"\n| " + ROOT_DIR +
"\n| Port: " +
"\n| " + PORT +
"\n| Usage: <directory> <port>" +
"\n| ctrl-c to exit" +
"\n==============================================");
/* The server is running */
while (isRunning) {
try {
/* Accept connection by client */
Socket socket = serverSocket.accept();
/* Each connected client gets a new thread */
new Thread(new RequestHandler(socket, ROOT_DIR)).start();
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
} catch (IOException e) {
System.err.println("Address already in use!" +
"\nClose running connection or choose other port");
}
} else
usageMsg();
System.exit(1);
}
public static boolean isDirectory(String path){
File filePath = null;
try{
filePath = new File(path);
/* False if file is not a directory */
if (!filePath.isDirectory())
return false;
}
catch (Exception e){
System.err.println(e.getMessage());
}
/* Seems to be a file path */
return true;
}
public static boolean isCorrect(String[] args){
if (args.length != 2){
usageMsg();
return false;
}
try{
ROOT_DIR = args[0].toString();
PORT = Integer.parseInt(args[1]);
}
catch (NumberFormatException n){
System.err.println(n.getMessage());
}
if (!isDirectory(ROOT_DIR)){
usageMsg();
return false;
}
return true;
}
public static void usageMsg(){
System.err.println("Invalid arguments"+
"\nUsage: java -jar Webserver.jar <directory> <port>");
}
}
RequestHandler:
import java.io.*;
import java.net.Socket;
import java.util.StringTokenizer;
/**
* Web Server Request Handler.
* Created on 2015-02-16.
*/
public class RequestHandler implements Runnable {
/*
TODO ( ) Problem 1
TODO ( ) Problem 2
TODO ( ) Problem 3
TODO (X) Index page for first page.
TODO (X) Read and download images & other files
TODO ( ) Fix header responses
TODO ( ) Error responses
*/
private String
OK = "HTTP/1.0 200 OK",
NOT_FOUND = "HTTP/1.0 404 Not Found",
BAD_REQUEST = "HTTP/1.0 400 Bad Request",
FORBIDDEN = "HTTP/1.0 403 Forbidden",
SERVER_ERROR = "HTTP/1.0 500 Internal Server Error";
private String ROOT_DIR;
private Socket client;
private PrintStream send;
private DataInputStream fromClient;
private DataOutputStream out;
RequestHandler(Socket client, String ROOT_DIR) {
this.client = client;
this.ROOT_DIR = ROOT_DIR;
try {
send = new PrintStream(client.getOutputStream());
fromClient = new DataInputStream(client.getInputStream());
out = new DataOutputStream(new BufferedOutputStream(client.getOutputStream()));
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
/* Reads the HTTP request and responds */
public void run() {
String request = null;
String fileName = null;
StringTokenizer tok = null;
try {
/* Read HTTP request from client */
while ((request = fromClient.readLine()) != null) {
System.out.println(request);
tok = new StringTokenizer(request);
/* Extracts the file path from the GET command */
if (tok.hasMoreElements() && tok.nextToken().equals("GET")
&& tok.hasMoreElements()) {
fileName = tok.nextToken();
} else
throw new FileNotFoundException();
/* */
if (fileName.endsWith("/"))
fileName += "index.html";
/* Illegal characters, prevent access to super directories */
if (fileName.indexOf("..") >= 0 || fileName.indexOf('|') >= 0
|| fileName.indexOf(':') >= 0 || fileName.indexOf('~') >= 0) {
error(FORBIDDEN, "Forbidden Access", fileName);
}
else
if (new File(fileName).isDirectory()) {
fileName = fileName.replace('\\', '/');
send.close();
return;
}
/* File name is ROOT_DIR + file name */
fileName = ROOT_DIR + fileName;
/* Create file */
File file = new File(fileName);
if (file.isDirectory()) {
fileName = fileName + "index.html";
}
/* File does not exist */
if (file.exists()){
/* Determines the MIME type of the file */
String mimeType = getMimeType(file);
/* Sends the file */
sendFile(file, mimeType, fileName);
client.close();
}
else
error(NOT_FOUND, "404 File Not Found", fileName);
}
}
catch (FileNotFoundException e) {
System.err.println(e.getMessage());
}
catch (IOException e){
System.err.println(e.getMessage());
}
}
/* Sends the requested file to the client */
public void sendFile(File file, String fileType, String fileName) {
try {
// Buffer must not be to low, => fragments
int length = (int) file.length();
FileInputStream fileIn = new FileInputStream(fileName);
byte[] bytes = new byte[length];
/* Write until bytes is empty */
while ((length = fileIn.read(bytes)) != -1 ){
out.write(bytes, 0, length);
out.flush();
out.writeBytes(OK);
out.writeBytes("Server: Jakobs Web Server v1.0");
out.writeBytes("Content-Type: " + fileType + "\r\n");
out.writeBytes("Content-Length: " + length + "\r\n");
out.writeBytes("");
}
send.close();
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
/* Sends the header response to the client */
public void sendHeaderResponse(String code, String fileType){
try {
out.writeBytes(code);
out.writeBytes("Server: Jakobs Web Server v1.0");
out.writeBytes("Content-Type: " + fileType + "\r\n");
out.writeBytes("");
}
catch (IOException e){
System.err.println(e.getMessage());
}
}
/* Sends error response to the client */
public void error(String code, String error, String fileName){
System.err.println(error +
"\nFile Requested: " + fileName);
/* Sends the error code header */
sendHeaderResponse(code, fileName);
/* Sends the error message and cause to client */
send.print("<html><head><title>" + error + "</title></head><body>");
send.print("<h1>" + error + "</h1>\r\n");
send.println("Location: /" + fileName + "/\r\n");
send.println("Exception Cause: " + error + "\r\n");
send.print("Start Page");
send.print("</body>\"</html>");
send.flush();
send.close();
}
/* Finds out the MIME type of the requested file */
public String getMimeType(File f) {
String file = f.toString();
String type = "";
if (file.endsWith(".txt")) {
type = "text/txt";
} else if (file.endsWith(".html") || file.endsWith("htm")) {
type = "text/html";
} else if (file.endsWith(".jpg")) {
type = "image/jpg";
} else if (file.endsWith(".png")) {
type = "image/png";
} else if (file.endsWith(".jpeg")) {
type = "image/jpeg";
} else if (file.endsWith(".gif")) {
type = "image/gif";
} else if (file.endsWith(".pdf")) {
type = "application/pdf";
} else if (file.endsWith(".mp3")) {
type = "audio/mpeg";
} else if (file.endsWith(".class")){
type = "application/octet-stream";
} else if (file.endsWith(".mp4")){
type = "video/mp4";
}
return type;
}
}
Make sure that you write e.g. HTTP/1.1 404 Not Found to the client, not just the 400.
Actually no, your problem is that you don't end the response properly. The browser keeps receiving data and shows no response code received. Let me see how this can be fixed in your code.
Also, you use two wrapper streams around client.getOutputStream() to send data to the client (send and out). Not sure why you do this. This looks weird. You should use just one wrapper stream. And you never close out, probably that's your problem, that's why the browser thinks the response is not yet fully received. Try to use one stream and handle it properly.
OK, here is your code fixed.
import java.io.*;
import java.net.Socket;
import java.util.StringTokenizer;
/**
* Web Server Request Handler.
* Created on 2015-02-16.
*/
public class RequestHandler implements Runnable {
/*
TODO ( ) Problem 1
TODO ( ) Problem 2
TODO ( ) Problem 3
TODO (X) Index page for first page.
TODO (X) Read and download images & other files
TODO ( ) Fix header responses
TODO ( ) Error responses
*/
private String
OK = "HTTP/1.0 200 OK",
NOT_FOUND = "HTTP/1.0 404 Not Found",
BAD_REQUEST = "HTTP/1.0 400 Bad Request",
FORBIDDEN = "HTTP/1.0 403 Forbidden",
SERVER_ERROR = "HTTP/1.0 500 Internal Server Error";
private String ROOT_DIR;
private Socket client;
private PrintStream send;
private DataInputStream fromClient;
// private DataOutputStream out;
RequestHandler(Socket client, String ROOT_DIR) {
this.client = client;
this.ROOT_DIR = ROOT_DIR;
try {
send = new PrintStream(client.getOutputStream());
fromClient = new DataInputStream(client.getInputStream());
// out = new DataOutputStream(new BufferedOutputStream(client.getOutputStream()));
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
/* Reads the HTTP request and responds */
public void run() {
String request = null;
String fileName = null;
StringTokenizer tok = null;
try {
/* Read HTTP request from client */
while ((request = fromClient.readLine()) != null) {
System.out.println(request);
tok = new StringTokenizer(request);
/* Extracts the file path from the GET command */
if (tok.hasMoreElements() && tok.nextToken().equals("GET")
&& tok.hasMoreElements()) {
fileName = tok.nextToken();
} else
throw new FileNotFoundException();
/* */
if (fileName.endsWith("/"))
fileName += "index.html";
/* Illegal characters, prevent access to super directories */
if (fileName.indexOf("..") >= 0 || fileName.indexOf('|') >= 0
|| fileName.indexOf(':') >= 0 || fileName.indexOf('~') >= 0) {
error(FORBIDDEN, "Forbidden Access", fileName);
}
else
if (new File(fileName).isDirectory()) {
fileName = fileName.replace('\\', '/');
send.close();
return;
}
/* File name is ROOT_DIR + file name */
fileName = ROOT_DIR + fileName;
/* Create file */
File file = new File(fileName);
if (file.isDirectory()) {
fileName = fileName + "index.html";
}
/* File does not exist */
if (file.exists()){
/* Determines the MIME type of the file */
String mimeType = getMimeType(file);
/* Sends the file */
sendFile(file, mimeType, fileName);
client.close();
}
else
error(NOT_FOUND, "404 File Not Found", fileName);
}
}
catch (FileNotFoundException e) {
System.err.println(e.getMessage());
}
catch (IOException e){
System.err.println(e.getMessage());
}
}
/* Sends the requested file to the client */
public void sendFile(File file, String fileType, String fileName) {
try {
// Buffer must not be to low, => fragments
int length = 0; // (int) file.length();
FileInputStream fileIn = new FileInputStream(fileName);
byte[] bytes = new byte[1024];
ByteArrayOutputStream bos = new ByteArrayOutputStream();
/* Write until bytes is empty */
while ((length = fileIn.read(bytes)) != -1 ){
bos.write(bytes, 0, length);
// send.write(bytes, 0, length);
// send.flush();
}
bos.flush();
bos.close();
byte[] data1 = bos.toByteArray();
System.out.print(new String(data1));
send.print(OK);
send.print("");
send.print("Server: Jakobs Web Server v1.0");
send.print("Content-Type: " + fileType + "\r\n");
send.print("Content-Length: " + data1.length + "\r\n");
send.println("");
send.write(data1, 0, data1.length);
send.println("");
send.flush();
send.close();
fileIn.close();
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
/* Sends the header response to the client */
public void sendHeaderResponse(String code, String fileType){
try {
send.print(code);
send.print("Server: Jakobs Web Server v1.0");
send.print("Content-Type: " + fileType + "\r\n");
send.print("");
send.println();
}
catch (Exception e){
System.err.println(e.getMessage());
}
}
/* Sends error response to the client */
public void error(String code, String error, String fileName){
System.err.println(error +
"\nFile Requested: " + fileName);
/* Sends the error code header */
sendHeaderResponse(code, fileName);
// send.println("ERROR");
/* Sends the error message and cause to client */
send.print("<html><head><title>" + error + "</title></head><body>");
send.print("<h1>" + error + "</h1>\r\n");
send.println("Location: /" + fileName + "/\r\n");
send.println("Exception Cause: " + error + "\r\n");
send.print("Start Page");
send.print("</body></html>");
send.flush();
send.close();
}
/* Finds out the MIME type of the requested file */
public String getMimeType(File f) {
String file = f.toString();
String type = "";
if (file.endsWith(".txt")) {
type = "text/txt";
} else if (file.endsWith(".html") || file.endsWith("htm")) {
type = "text/html";
} else if (file.endsWith(".jpg")) {
type = "image/jpg";
} else if (file.endsWith(".png")) {
type = "image/png";
} else if (file.endsWith(".jpeg")) {
type = "image/jpeg";
} else if (file.endsWith(".gif")) {
type = "image/gif";
} else if (file.endsWith(".pdf")) {
type = "application/pdf";
} else if (file.endsWith(".mp3")) {
type = "audio/mpeg";
} else if (file.endsWith(".class")){
type = "application/octet-stream";
} else if (file.endsWith(".mp4")){
type = "video/mp4";
}
return type;
}
}

Java Server: Socket sending HTML code to browser

I am trying to write a simple Java program using ServerSockets that will send some HTML code to the browser. Here is my code:
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(55555);
} catch (IOException e) {
System.err.println("Could not listen on port: 55555.");
System.exit(1);
}
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
if(clientSocket != null) {
System.out.println("Connected");
}
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
out.println("HTTP/1.1 200 OK");
out.println("Content-Type: text/html");
out.println("\r\n");
out.println("<p> Hello world </p>");
out.flush();
out.close();
clientSocket.close();
serverSocket.close();
I then go to localhost:55555 in my browser and nothing displays. I know the connection is working because the program outputs "Connected" as checked in the if statement. I have also tried outputting the data from the inputStream and that works. But the text I am trying to output in the browser is not displaying at all, the program finishes running and I get a
"Problem loading page - the connection has been reset"
in my browser, but no text.
I have searched the internet and it seems everyone else coding it this way is having their text display fine, they are having other problems.
How can I fix this?
I tested your code in Chrome, Firefox, IE, and Opera and it works.
However, I would suggest that you use multi-threading and essentially spawn a new thread to handle each new request.
You can create a class that implements runnable and takes a clientSocket within the constructor. This will essentially make your custom webserver capable of accepting more than one request concurrently.
You will also need a while loop if you want to handle more than one total requests.
A good read demonstrating the above: https://web.archive.org/web/20130525092305/http://www.prasannatech.net/2008/10/simple-http-server-java.html
If the web-archive is not working, I'm posting the code below (taken from above):
/*
* myHTTPServer.java
* Author: S.Prasanna
* #version 1.00
*/
import java.io.*;
import java.net.*;
import java.util.*;
public class myHTTPServer extends Thread {
static final String HTML_START =
"<html>" +
"<title>HTTP Server in java</title>" +
"<body>";
static final String HTML_END =
"</body>" +
"</html>";
Socket connectedClient = null;
BufferedReader inFromClient = null;
DataOutputStream outToClient = null;
public myHTTPServer(Socket client) {
connectedClient = client;
}
public void run() {
try {
System.out.println( "The Client "+
connectedClient.getInetAddress() + ":" + connectedClient.getPort() + " is connected");
inFromClient = new BufferedReader(new InputStreamReader (connectedClient.getInputStream()));
outToClient = new DataOutputStream(connectedClient.getOutputStream());
String requestString = inFromClient.readLine();
String headerLine = requestString;
StringTokenizer tokenizer = new StringTokenizer(headerLine);
String httpMethod = tokenizer.nextToken();
String httpQueryString = tokenizer.nextToken();
StringBuffer responseBuffer = new StringBuffer();
responseBuffer.append("<b> This is the HTTP Server Home Page.... </b><BR>");
responseBuffer.append("The HTTP Client request is ....<BR>");
System.out.println("The HTTP request string is ....");
while (inFromClient.ready())
{
// Read the HTTP complete HTTP Query
responseBuffer.append(requestString + "<BR>");
System.out.println(requestString);
requestString = inFromClient.readLine();
}
if (httpMethod.equals("GET")) {
if (httpQueryString.equals("/")) {
// The default home page
sendResponse(200, responseBuffer.toString(), false);
} else {
//This is interpreted as a file name
String fileName = httpQueryString.replaceFirst("/", "");
fileName = URLDecoder.decode(fileName);
if (new File(fileName).isFile()){
sendResponse(200, fileName, true);
}
else {
sendResponse(404, "<b>The Requested resource not found ...." +
"Usage: http://127.0.0.1:5000 or http://127.0.0.1:5000/</b>", false);
}
}
}
else sendResponse(404, "<b>The Requested resource not found ...." +
"Usage: http://127.0.0.1:5000 or http://127.0.0.1:5000/</b>", false);
} catch (Exception e) {
e.printStackTrace();
}
}
public void sendResponse (int statusCode, String responseString, boolean isFile) throws Exception {
String statusLine = null;
String serverdetails = "Server: Java HTTPServer";
String contentLengthLine = null;
String fileName = null;
String contentTypeLine = "Content-Type: text/html" + "\r\n";
FileInputStream fin = null;
if (statusCode == 200)
statusLine = "HTTP/1.1 200 OK" + "\r\n";
else
statusLine = "HTTP/1.1 404 Not Found" + "\r\n";
if (isFile) {
fileName = responseString;
fin = new FileInputStream(fileName);
contentLengthLine = "Content-Length: " + Integer.toString(fin.available()) + "\r\n";
if (!fileName.endsWith(".htm") && !fileName.endsWith(".html"))
contentTypeLine = "Content-Type: \r\n";
}
else {
responseString = myHTTPServer.HTML_START + responseString + myHTTPServer.HTML_END;
contentLengthLine = "Content-Length: " + responseString.length() + "\r\n";
}
outToClient.writeBytes(statusLine);
outToClient.writeBytes(serverdetails);
outToClient.writeBytes(contentTypeLine);
outToClient.writeBytes(contentLengthLine);
outToClient.writeBytes("Connection: close\r\n");
outToClient.writeBytes("\r\n");
if (isFile) sendFile(fin, outToClient);
else outToClient.writeBytes(responseString);
outToClient.close();
}
public void sendFile (FileInputStream fin, DataOutputStream out) throws Exception {
byte[] buffer = new byte[1024] ;
int bytesRead;
while ((bytesRead = fin.read(buffer)) != -1 ) {
out.write(buffer, 0, bytesRead);
}
fin.close();
}
public static void main (String args[]) throws Exception {
ServerSocket Server = new ServerSocket (5000, 10, InetAddress.getByName("127.0.0.1"));
System.out.println ("TCPServer Waiting for client on port 5000");
while(true) {
Socket connected = Server.accept();
(new myHTTPServer(connected)).start();
}
}
}
Enjoy!
You need to need to set the PrintWriter to autoflush when it prints.
PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
should be
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
The line terminator in HTTP is \r\n. This means that you shouldn't use println(), you should use print() and add an explicit \r\n yourself to each line.
The result of an HTTP GET is supposed to be an HTML document, not a fragment. Browsers are entitled to ignore or complain. Send this:
<html>
<head/>
<body>
<p> Hello world </p>
</body>
</html>
in my computer, at least to get the socket's inputStream:
clientSocket.getInputStream();
with out this line, sometimes chrome doesn't work
you need read the input from socket first
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String line = "";
while((line = bufferedReader.readLine()) != null){
System.out.println(line);
if(line.isEmpty())
break;
}
You should accept the request sent by client(browser in this case),to do that just add the following lines:
Buffered reader in = new Buffered reader(new InputStreamReader(client_socket.getInputStream()));
Note: you need to replace the "client_socket" part with name of your own socket for the client.
Why we need to accept browser request?
It's because if we don't accept the request browser doesn't get any acknowledgement from the server that the request that was sent is received,hence it thinks the server is not reachable any more.
My code:
public class Help {
public static void main(String args) throws IOException{
ServerSocket servsock new serverSocket(80)
Socket cs servsock, accept();
Printwriter out new Printwriter(Cs.getoutputstream), true)
BufferedReader in new BufferedReader(new InputStreamReader(cs.getInputStream());
out.println("<html> <body> <p>My first StackOverflow answer </p> </body> </html>");
out.close();
servsock.close();
}
}
You need to send
"HTTP/1.1 200 OK" first. followed by a newline
then "Content-Type: text/html; charset: UTF-8" followed by 2 newlines.
then send the HTML source for it to display as a styled webpage and not just a text output.
I used OutputStreamWriter
OutputStreamWriter osw = new OutputStreamWriter(socket.getOutputStream());
osw.write("HTTP/1.1 200 OK\nContent-Type: text/html; charset=UTF-8\n\n");
osw.write("<html><head><title>Hello World</title></head><body></body><p>Hello World</p></body></html>");
Not sending "HTTP/1.1 200 OK" first results in source code being displayed without html parsing..
And to avoid "Connection being reset" error, you need to close your socket. Very Important !!
The whole code:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class WebServer
{
ServerSocket serverSocket;
Socket socket;
FileReader fr;
OutputStreamWriter osw;
WebServer() throws IOException
{
serverSocket = new ServerSocket(8080);
socket = serverSocket.accept();
fr = new FileReader("index.html");
osw = new OutputStreamWriter(socket.getOutputStream());
osw.write("HTTP/1.1 200 OK\nContent-Type: text/html; charset=UTF-8\n\n");
int c;
char[] ch = new char[4096];
while ((c = fr.read(ch)) != -1)
{
osw.write(ch, 0, c);
}
osw.close();
socket.close();
}
public static void main(String[] args) throws IOException
{
new WebServer();
}
}

HttpRequest in Java: Always goes to 404

I wrote this HttpRequest method, but for some reason it always goes to 404 Not Found, even though the file location exists when the java process isn't running.
import java.io.*;
import java.net.*;
import java.util.*;
final class HttpRequest implements Runnable {
final static String CRLF = "\r\n";
Socket socket;
// Constructor
public HttpRequest(Socket socket) throws Exception {
this.socket = socket;
}
// Implement the run() method of the Runnable interface.
public void run() {
try {
processRequest();
} catch (Exception e) {
System.out.println(e);
}
}
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 socket's output stream.
while((bytes = fis.read(buffer)) != -1 ) {
os.write(buffer, 0, bytes);
}
}
private static String contentType(String fileName) {
if(fileName.endsWith(".htm") || fileName.endsWith(".html")) {
return "text/html";
}
if(fileName.endsWith(".jpeg") || fileName.endsWith(".jpg")) {
return "image/jpeg";
}
if(fileName.endsWith(".gif")) {
return "image/gif";
}
return "application/octet-stream";
}
private void processRequest() throws Exception {
// Get a reference to the socket's input and output streams.
InputStream is = socket.getInputStream();
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
// Set up input stream filters.
BufferedReader br = new BufferedReader(new InputStreamReader(is));
// Get the request line of the HTTP request message.
String requestLine = new String(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);
}
// 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;
// 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 = "200 OK" + CRLF;
contentTypeLine = "Content-type: " +
contentType( fileName ) + CRLF;
} else {
statusLine = "404 NOT FOUND" + CRLF;
contentTypeLine = "Content Not Found!" + 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 line.
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("File DNE: Content Not Found!");
}
// Close streams and socket.
os.close();
br.close();
socket.close();
}
}
Any help would be greatly appreciated...I feel like it's something simple I'm missing.
I ran your code; it works fine (except for some minor issues with not printing the headers correctly, which every browser I've tried is willing to completely ignore).
Are you sure your working directory is where you expect? Try changing the 404 message to something like:
contentTypeLine = "Content Not Found: " + new File(fileName).getAbsolutePath() + CRLF;
For reference, I ran it with a test harness of:
public static void main(String[] args) throws Exception {
final ServerSocket ss = new ServerSocket(8080);
while (true)
new HttpRequest(ss.accept()).run();
}

Categories