Trouble sending HTTP response with Java Socket

2019-02-18 02:53发布

问题:

I've been trying to write the beginnings of a simple web server, but can't seem to get the response to get sent. I've tried every type of Output stream imaginable but nothing seems to work. I'm at a loss. Here are the two classes I'm using, sorry about some of the extraneous code:

package edu.xsi.webserver;

import java.io.IOException;
import java.net.ServerSocket;


public class WebServer {

int port;
ServerSocket server;

public WebServer(int port) throws IOException{

    this.port = port;
    this.server = new ServerSocket(port);
    Thread t = new Thread(new ServerExec());
    t.start();

}

public class ServerExec implements Runnable {

    public void run(){

        int i = 0;
        while (true) {

            try {
                new WebSession(server.accept(), i++);
                System.out.println("Should print before session");
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }


}

public static void main(String[] args) {

    try {
        WebServer webServer = new WebServer(8888);
    } catch (IOException e) {
        e.printStackTrace();
    }
}
}

This is the session class that handles the response.

package edu.xsi.webserver;

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;

public class WebSession implements Runnable {

Socket client;
int num;

public WebSession(Socket client, int num) {

    this.num = num;
    this.client = client;
    Thread t = new Thread(this);
    t.start();
}


public void run() {

    Scanner s = null;
    DataOutputStream out = null;

    try {

        s = new Scanner(client.getInputStream());
        out = new DataOutputStream(client.getOutputStream());

        //Get all input from header
        while (s.hasNextLine()) {
            System.out.println(s.nextLine());
        }
        out.writeBytes("HTTP/1.1 200 OK\r\n");
        out.writeBytes("Content-Type: text/html\r\n\r\n");
        out.writeBytes("<html><head></head><body><h1>Hello</h1></body></html>");

        s.close();
        out.flush();
        out.close();

    } catch(IOException ioe) {

        ioe.printStackTrace();
    }

}

}

回答1:

I've been struggling like crazy with a very similar issue.

After literally head-banding on the wall I found my issue was so trivial I kept on head-banging on the wall for a while.

Basically in my input while loop I was checking for a null line, but I forgot to check for an empty line (and subsequently break).

No guarantee it'll work the same for you but here's my one cent:

in = session.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line = null;
while ((line = br.readLine()) != null) {
    System.out.println(line);
    // this seems to be the key for me! 
    // somehow I never get out of this loop if I don't 
    // check for an empty line...
    if (line.isEmpty()) {
        break;
    }
}
out = new BufferedWriter(
    new OutputStreamWriter(
        new BufferedOutputStream(session.getOutputStream()), "UTF-8")
);
out.write(OUTPUT_HEADERS + OUTPUT.length() + OUTPUT_END_OF_HEADERS + OUTPUT);
out.flush();
out.close();
session.close();

My constants are:

private static final String OUTPUT = "<html><head><title>Example</title></head><body><p>Worked!!!</p></body></html>";
private static final String OUTPUT_HEADERS = "HTTP/1.1 200 OK\r\n" +
    "Content-Type: text/html\r\n" + 
    "Content-Length: ";
private static final String OUTPUT_END_OF_HEADERS = "\r\n\r\n";

My "session" variable is a Socket object.



回答2:

Closing the Scanner closes the underlying input stream, which closes the socket. Don't close it. Closing the output stream also closes the socket. You don't need both, and you should close the output stream/writer rather than the input stream so it gets flushed.



回答3:

The below code will solve your problem:

package com.cs.sajal;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class TestCls {

    public static void main(String[] args) {
        boolean flag = false;

        try {
            ServerSocket ss = new ServerSocket(8080);
            if (ss.isBound()) {
                while (flag = true) {
                    final Socket s = ss.accept();



                    Thread t1=new Thread(new Runnable (){String line = null;public void run(){try{ InputStream is = s.getInputStream();
                    BufferedReader br = new BufferedReader(
                            new InputStreamReader(is));

                    while ((line = br.readLine()) != null) {
                        System.out.println(line);
                    }
                    }
                    catch(Exception e)
                    {
                        e.printStackTrace();
                    }
                    }});

                    Thread t2=new Thread(new Runnable (){String line = null;public void run(){try{ OutputStream os = s.getOutputStream();
                    Scanner sc=new Scanner(System.in);
                    String inp=null;
                    String t="HTTP/1.1 200 OK\r\n";
                    byte[]s=t.getBytes("UTF-8");
                    os.write(s);

                    t="Content-Length: 788\r\n";
                    s=t.getBytes("UTF-8");
                    os.write(s);
                    t="Content-Type: text/html\r\n\r\n";
                    s=t.getBytes("UTF-8");
                    os.write(s);


                    t="\r\n\r\n<html><body><h1>this is output</h1><table cellpading=5 border=5><tr><td>name</td><td>age></td><td>height</td></tr></table></body></html>\r\n\r\n";
                    s=t.getBytes("UTF-8");
                    os.write(s);
                    t="Connection: Closed";
                    s=t.getBytes("UTF-8");
                    os.write(s);

                    os.flush();
                    }
                    catch(Exception e)
                    {
                        e.printStackTrace();
                    }
                    }});
                    t1.start();
                    t2.start();t1.join();
                    t2.join();


                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


回答4:

Try pass the date.

 String res = "HTTP/1.0 200 OK\n"
         + "Server: HTTP server/0.1\n";
         + "Date: "+format.format(new java.util.Date())+"\n"; 
   + "Content-type: text/html; charset=UTF-8\n"; 
         + "Content-Length: 38\n\n";
         + "<html><body>OK</body></html>";
out.write(res.getBytes());
out.flush();

private SimpleDateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:Ss z");