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.