I know you don't technically don't do homework here, but can you at least help with homework? There's a slight problem with my code that I hope you will help me with.
Basically, I'm learning to make a simple multithreaded HTTP request/response server using Java. I could make a single thread that does one HTTP request/response... and I've done multithreading in the past, though not quite in this way. My problem mostly seems to be in mixing the two. I keep getting nullPointerException errors, and I dunno why. I've debugged it over and over, and nothing seems wrong.
Could you point out any possible solutions I should try? Effectively what it's doing, or at least what it should be doing, with each thread is making a socket for talking to the browser, takes the GET request, and sends the requested file as raw byte data. I managed to get it working with a single thread, and it would send the basic index.html file, but then it'd break on the second loop on a nullPointerException. I thought that setting up as multiple threads might help fix that, but it doesn't seem to.
Code:
package lab4;
import java.io.*;
import java.net.*;
/**
* A server that handles multiple HTTP requests
* @author dmloveless
*/
public class WebServer {
public static String array[];
public static void main(String[] args) {
BufferedReader jin = new BufferedReader(new InputStreamReader(System.in));
int port = 0;
try {
if (args.length == 0) {
String input;
System.out.print("Server Port: ");
input = jin.readLine();
array = input.split(" ");
port = Integer.parseInt(array[0]);
}
else { port = Integer.parseInt(args[0]); }
TServSock Server = new TServSock(port);
while ( true ) {
TIMSock client = Server.engage();
new Thread( new WorkerRunnable( client ) ).start();
}
}
catch (Exception ex) {
System.out.println("Exception caught in thread: " + ex);
}
}
}
class TIMSock {
private Socket sock;
private BufferedReader jin;
private PrintWriter jout;
TIMSock(InetAddress Host, int Port) throws SocketException, IOException{
sock = new Socket(Host, Port);
setIO();
}
TIMSock(Socket sock) throws IOException {
this.sock = sock;
setIO();
}
private void setIO() throws IOException{
InputStream inStream = sock.getInputStream();
jin = new BufferedReader(new InputStreamReader(inStream));
OutputStream outStream = sock.getOutputStream();
jout = new PrintWriter(new OutputStreamWriter(outStream));
}
public InputStream rawIn() throws IOException {
return sock.getInputStream();
}
public OutputStream rawOut() throws IOException {
return sock.getOutputStream();
}
public void IMsend(String message) throws IOException {
jout.println(message);
jout.flush();
}
public String IMreceive() throws IOException {
String message = jin.readLine();
return message;
}
public void timer(int time) throws SocketException {
sock.setSoTimeout(time);
}
public void close() throws IOException{ sock.close(); }
}
class TServSock {
private ServerSocket serv;
TServSock(int Port) throws SocketException, IOException{
serv = new ServerSocket(Port);
}
TServSock(ServerSocket serv) throws IOException {
this.serv = serv;
}
public TIMSock engage() throws IOException, NullPointerException {
return new TIMSock(serv.accept());
}
public void close() throws IOException{ serv.close(); }
}
class WorkerRunnable implements Runnable{
private TIMSock sock = null;
private String input = null;
public WorkerRunnable(TIMSock clientSocket) {
this.sock = clientSocket;
}
public void run() {
try {
input = sock.IMreceive();
if (input != null) {
HttpRequest HR = new HttpRequest(input);
HR.response(sock.rawOut());
}
} catch (IOException e) {
e.printStackTrace();
}
}
} Code:
package lab4;
import java.io.*;
import java.net.*;
import java.util.*;
/**
* Handles a individual HTTP request
* @author dmloveless
*/
public class HttpRequest {
private String method;
private String file;
private String protocol;
private Scanner fis;
public String request;
HttpRequest( String request ) throws SocketException, IOException {
this.request = request;
}
public void response( OutputStream fout ) throws SocketException, IOException {
String response = "";
StringTokenizer message = new StringTokenizer(request);
method = message.nextToken().toString();
file = message.nextToken().toString();
protocol = message.nextToken().toString();
final int BUFFER = 2048;
byte[] bytes = new byte[BUFFER];
FileInputStream fis = null;
if ( !method.equals("GET") ) {
response = "HTTP/1.1 504 UNKNOWN METHOD/r/n";
}
boolean fileExists = true;
try {
File HTML = new File(file.replaceFirst("/",""));
if (HTML.exists()) {
fis = new FileInputStream(HTML);
}
}
catch (FileNotFoundException e) {
if ( file.equals("/") ) {
response = "HTTP/1.1 200 OK\r\n" +
"Content-Type: text/html\r\n" +
"Content-Length: 46\r\n" +
"\r\n" +
"<html>\r\n" +
"<body>\r\n" +
"<p>Hello, World!</p>\r\n" +
"</body>\r\n" +
"</html>\r\n";
fout.write(response.getBytes());
}
else fileExists = false;
}
boolean validProtocol;
if (protocol.equals("HTTP/1.0") || protocol.equals("HTTP/1.1")) { validProtocol = true; }
else { validProtocol = false; }
if ( fileExists && validProtocol ) {
Scanner fin = new Scanner(fis);
response = "HTTP/1.1 200 OK\r\n" +
"Content-Type: text/html\r\n" +
"\r\n";
while (fin.hasNextLine()) { response += fin.nextLine().toString() + "\r\n"; }
fout.write(response.getBytes());
}
else {
if ( !fileExists ) response = "HTTP/1.1 404 FILE NOT FOUND\r\n" +
"Content-Type: text/html\r\n" +
"Content-Length: 23\r\n" +
"\r\n" +
"<h1>File Not Found</h1>";
fout.write(response.getBytes());
if ( !validProtocol ) response = "HTTP/1.1 505 INVALID PROTOCOL\r\n" +
"Content-Type: text/html\r\n" +
"Content-Length: 25\r\n" +
"\r\n" +
"<h1>Version too old!</h1>";
fout.write(response.getBytes());
}
}
}