-1

I get this error all the time tried everything switching JVMs and stuff changing code itself but nothing really works Chat GPT also doesn't help. If someone know what's the dead with this please help. I really want to understand what's wrong with it.

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class HttpServer {
    private final int port;

    public HttpServer(final int port) {
        this.port = port;
    }

    public void run() {
        try(var serverSocket = new ServerSocket(port)) {
                var socket = serverSocket.accept();
                System.out.println("Socket accepted");
                processSocket(socket);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void processSocket(Socket socket) throws IOException {
        try(socket;
            var inputStream = new DataInputStream(socket.getInputStream());
            var outputStream = new DataOutputStream(socket.getOutputStream())) {

            System.out.println(new String(inputStream.readNBytes(100)));
            byte[] body = Files.readAllBytes(Path.of("src/main/resources/example.html"));
            outputStream.write("""
                    HTTP/1.1 200 OK
                    content-type: text/html
                    content-length: %s
                    """.formatted(body.length).getBytes());
            outputStream.write(System.lineSeparator().getBytes());
            outputStream.write(body);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}



import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;
import java.util.concurrent.ExecutionException;

import static java.net.http.HttpRequest.BodyPublishers.ofFile;

public class HttpClientRunner {
    public static void main(final String[] args) throws IOException, InterruptedException, ExecutionException {
        var httpClient = HttpClient.newBuilder()
                .version(HttpClient.Version.HTTP_1_1)
                .build();
        var request = HttpRequest.newBuilder()
                .uri(URI.create("http://localhost:8082"))
                .header("content-type", "application/json")
                .POST(ofFile(Path.of("src/main/resources/example.json")))
                .build();

        var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

        System.out.println(response.headers());
        System.out.println(response.body());
    }
}

Tried to search everywhere but found literally nothing.

3
  • 1
    "tried everything switching JVMs and stuff changing code itself but nothing really works Chat GPT also doesn't help." You are not describing any detail of what you did, or what symptoms are you observing. Please read How to Ask then edit then question with more clarifications. Commented Feb 11 at 16:22
  • 1
    This question is similar to: java: read vs readNBytes of the InputStream instance. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. Commented Feb 11 at 16:26
  • readNBytes might block. But you don't explain where your code is deviating from your expectations, so all we can do is guess. Commented Feb 11 at 16:27

2 Answers 2

0

I'm going to guess here. As others have noted your question is half formed. The obvious issue is that you haven't posted the error you are receiving or described what behavior you are encountering that is unexpected. It's always good to include the expected behavior too. That being said if I execute your code as is (I removed the 2 external files and hard coded strings in their place). I get this:

Exception in thread "main" java.net.ConnectException
    at java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:951)
    at java.net.http/jdk.internal.net.http.HttpClientFacade.send(HttpClientFacade.java:133)
    at Scratch.main(Scratch.java:64)
Caused by: java.net.ConnectException
    at java.net.http/jdk.internal.net.http.common.Utils.toConnectException(Utils.java:1028)
    at java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:227)
    at java.net.http/jdk.internal.net.http.PlainHttpConnection.checkRetryConnect(PlainHttpConnection.java:280)
    at java.net.http/jdk.internal.net.http.PlainHttpConnection.lambda$connectAsync$2(PlainHttpConnection.java:238)
    at java.base/java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:934)
    at java.base/java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:911)
    at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
    at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1773)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
    at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.nio.channels.ClosedChannelException
    at java.base/sun.nio.ch.SocketChannelImpl.ensureOpen(SocketChannelImpl.java:202)
    at java.base/sun.nio.ch.SocketChannelImpl.beginConnect(SocketChannelImpl.java:786)
    at java.base/sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:874)
    at java.net.http/jdk.internal.net.http.PlainHttpConnection.lambda$connectAsync$1(PlainHttpConnection.java:210)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:571)
    at java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:212)
    ... 9 more

The reason for this is your code never starts the HTTP server. There are 2 solutions for this.

  • Create a new thread and have the server run on that thread
  • Use a separate process for the server (ie two JVMs)

Option 1: New Thread: Make your HttpServer implement Runnable so that we can pass it to a thread instance and it'll know how to execute it.

public class HttpServer implements Runnable {

Main method:


    public static void main(String[] args) throws IOException, InterruptedException {
        HttpServer server = new HttpServer(8088);
        Thread serverThread = new Thread( server );
        try {
            serverThread.start();
            
            var httpClient = HttpClient.newBuilder()
                    .version(HttpClient.Version.HTTP_1_1)
                    .build();
            var request = HttpRequest.newBuilder()
                    .uri(URI.create("http://localhost:8088"))
                    .header("content-type", "application/json")
                    .POST(ofString("{\"test\":\"this is a test\"}"))
                    .build();
    
            var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
    
            System.out.println(response.headers());
            System.out.println(response.body());
        } finally {
            serverThread.interrupt(); // cause the server to shut itself down gracefully
        }
    }

Option 2 - Separate processes

Add a main method to HttpServer to start the server.

    public class HttpServer implements Runnable {

        private final int port;

        public HttpServer(final int port) {
            this.port = port;
        }

        public void run() {
            try(var serverSocket = new ServerSocket(port)) {
                var socket = serverSocket.accept();
                processSocket( socket );  // you weren't calling the processSocket method!
                System.out.println("Socket accepted");
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("Shutdown");
            }
        }

        private void processSocket(Socket socket) throws IOException {
            try(socket;
                var inputStream = new DataInputStream(socket.getInputStream());
                var outputStream = new DataOutputStream(socket.getOutputStream())) {

                System.out.println(new String(inputStream.readNBytes(100)));
                byte[] body = "<html><body>Hello World</body></html>\n".getBytes("UTF-8");

                outputStream.write("""
                    HTTP/1.1 200 OK
                    content-type: text/html
                    content-length: %s
                    """.formatted(body.length).getBytes());
                outputStream.write(System.lineSeparator().getBytes());
                outputStream.write(body);
            }
        }

        public static void main(String[] args) {
            HttpServer server = new HttpServer(8088);
            server.run();
        }
    }

I had to invoke the processSocket method because it wasn't being done in your code. Without that nothing would happen, and probably everything would hang.

If you go with option 2 which is probably the better idea. You'll need to modify the code from option 1 to remove the section where I started a thread. The only changes I made for that code block were the port (8082 -> 8088), hard coded the JSON payload, and starting up/shutting down of the server. You can use your code instead, but just remember I changed the port.

After doing these changes I did get your code to execute and run to completion.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks I tried it multiple time it might've even worked once Idk but now I try your second option by staring the server first on port 8088 and then running the client and this is what I get in HttpClientRunner: Exception in thread "main" java.io.IOException: HTTP/1.1 header parser received no bytes at java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:586) In HttpServer I get this: POST / HTTP/1.1 Content-Length: 25 Host: localhost:8088 User-Agent: Java-http-client/17.0.0.1 co Socket accepted
The exception you received in the client is because the server didn't respond correctly. This is most likely because there was an exception in the server. So go look at the output from the server's program to see that exception. You should see the stack trace and the line "Shutdown" on the console. That's how you'll know you're on the right console.
0

So I couldn't figure it out on my own but thanks to initial response here and then feeding the code to chat GPT it gave some results although it looks quite different now but now it actually works both ways reading from json and html file respectively.

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class HttpServer implements Runnable {

    private final int port;
   // private final ExecutorService executor = Executors.newFixedThreadPool(5);

    public HttpServer(final int port) {
        this.port = port;
    }

    public void run() {
        try (var serverSocket = new ServerSocket(port)) {
            System.out.println("Server started on port " + port);
/*            while (true) {
                var socket = serverSocket.accept();
                executor.submit(() -> handleClient(socket));
            }*/
            var socket = serverSocket.accept();
            handleClient(socket);

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

    private void handleClient(Socket socket) {
        try (socket;
             var inputStream = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
             var outputStream = new DataOutputStream(socket.getOutputStream())) {

            
            String line;
            int contentLength = 0;
            while (!(line = inputStream.readLine()).isBlank()) {
                System.out.println("Header: " + line);
                if (line.toLowerCase().startsWith("content-length:")) {
                    contentLength = Integer.parseInt(line.split(":")[1].trim());
                }
            }

            
            if (contentLength > 0) {
                char[] buffer = new char[contentLength];
                inputStream.read(buffer, 0, contentLength);
                System.out.println("Received body: " + new String(buffer));
            }

            
            Path filePath = Path.of("src/main/resources/site.html");
            byte[] body = Files.readAllBytes(filePath);
            
            outputStream.write((
                    "HTTP/1.1 200 OK\r\n" +
                            "Content-Type: text/html\r\n" +
                            "Content-Length: " + body.length + "\r\n" +
                            "\r\n"  
            ).getBytes(StandardCharsets.UTF_8));
            outputStream.write(body);
            outputStream.flush();

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

    public static void main(String[] args) {
        new Thread(new HttpServer(8082)).start();
    }
}



import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;

import static java.net.http.HttpRequest.BodyPublishers.ofFile;

public class HttpClientRunner {
    public static void main(final String[] args) throws IOException, InterruptedException {
        var httpClient = HttpClient.newBuilder()
                .version(HttpClient.Version.HTTP_1_1)
                .build();

        Path jsonFilePath = Path.of("src/main/resources/example.json");
        var request = HttpRequest.newBuilder()
                .uri(URI.create("http://localhost:8082"))
                .header("Content-Type", "application/json")
                .POST(ofFile(jsonFilePath))
                .build();

        var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

        System.out.println("Response headers: " + response.headers());
        System.out.println("Response body: " + response.body());
    }
}

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.