I’m making an android app that acts like a web server to send files across HTTP while trying to the connection alive.
The problem is that when I try to send request to the android server to load the page the browser keeps loading forever.
I tried with curl and there is a response but not fully sent.
As you can see in this image the last </html> tag is missing.
And these are the headers received by curl
┌─[ammar@archlinux]─[~]
└──╼ curl http://192.168.1.7:2999/ -i
HTTP/1.1 200 OK
Keep-Alive: timeout=5
Connection: keep-alive
Content-Type: text/html
This is the code I use to accept requests.
private void Accept() {
try {
while (!serverSocket.isClosed()) {
Socket clientSocket = serverSocket.accept();
// downloadablesList is a list of files available to be sent.
ClientHandler clientHandler = new ClientHandler(downloadablesList, clientSocket);
Thread clientThread = new Thread(clientHandler);
clientThread.start();
}
} catch (SocketException e) {
// this exception is caught when calling socket.close();
} catch (IOException e) {
Log.e("MYLOG", e.getMessage());
}
}
ClientHandler
is basically a class the implements Runnable
here is its run
method and its constructor.
public ClientHandler(LinkedList<Downloadable> downloadablesList, Socket clientSocket) {
this.downloadablesList = downloadablesList;
this.clientSocket = clientSocket;
}
// handle client here
@Override
public void run() {
// use this variable later
String clientAddress = clientSocket.getRemoteSocketAddress().toString();
try {
clientSocket.setKeepAlive(true);
clientSocket.setSoTimeout(timeout);
} catch (SocketException e) {
Log.e("MYLOG", e.getMessage());
}
Request request = new Request(clientSocket);
// readSocket() just reads from clientSocket with InputStream and parse the request.
while(request.readSocket()) {
String path = request.getPath();
Response response = new Response(clientSocket);
// multiply timeout by 0.001 to convert from milliseconds into seconds
response.setHeader("Connection", "keep-alive");
response.setHeader("Keep-Alive", String.format(Locale.ENGLISH, "timeout=%d", (int)(timeout * 0.001)));
if ("/".equals(path) || "/index.html".equals(path)) {
response.setHeader("Content-Type", "text/html");
response.sendResponse(NetworkService.readFileFromAssets("index.html"));
}
// check for diffrent pathes here with else-if
else {
response.setStatusCode(404);
response.setHeader("Content-Type", "text/html");
response.sendResponse("404 What are you doing ?".getBytes(StandardCharsets.UTF_8));
}
}
}
this is request.readSocket()
public boolean readSocket() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()), 1024);
params = new HashMap<>();
int lineNumber = 1;
String line;
while (!(line = br.readLine()).isEmpty()) {
handleHTTPHeader(line, lineNumber);
lineNumber++;
}
return true;
} catch (SocketTimeoutException e) {
return false;
} catch (NullPointerException e) {
// for some reason this is thrown when Pipe is broken especially when using Ctrl + C with curl and Broken Pipe message in outputed probably when trying to write to socket later on and the logcat goes crazy
return false;
} catch (Exception e) {
Log.e("MYLOG", e.getMessage());
return false;
}
}
Here is the code of response.sendResponse
public void sendResponse(byte[] content) {
try {
OutputStream out = clientSocket.getOutputStream();
writeHeaders(out);
out.write(content);
out.flush();
} catch (IOException e) {
Log.e("MYLOG", e.getMessage());
}
}