【问题标题】:Unable to retrieve input stream data from httpExchange无法从 httpExchange 检索输入流数据
【发布时间】:2016-11-24 15:40:10
【问题描述】:

我已经为 http 服务器编写了一个代码,它假设根据客户端输入向客户端发送响应。

我已经写了两次相同的代码,一次使用简单的套接字连接,第二次使用com.sun.net.httpserver

基于简单套接字的代码工作正常,我可以使用以下方式读取来自客户端的请求:

DataInputStream in = new DataInputStream (threadSocket.getInputStream());
int ln = in.available();
byte [] bytes  = new byte [ln];
in.read(bytes);
String msg = new String(bytes);

但是,当我尝试使用 httpserver 时,我无法从客户端获得任何输入。

这是 http server hendler 的代码:

static class ntripHandler implements HttpHandler {
    public void handle(HttpExchange t){ 
        try {
            int ln = t.getRequestBody().available();
            byte [] bt  = new byte [ln];
            t.getRequestBody().read(bt);
            String msg = new String(bt);
            System.out.println(msg);
        } 
        catch (IOException ex) {System.out.println(ex);}

        //// some operations sholuld be made here .......

    }
}

目前,我正在尝试使用来自HttpExchange.getRequestBody() 的输入流,但它始终为空。我也试过httpExchange.getRequestURI().getQuery(),但它也总是为空。

来自客户端的输入如下所示: GET / HTTP/1.0 User-Agent: NTRIP GnssSurferV1.10 Authorization: Basic

我做错了什么,我该如何解决?任何帮助将不胜感激。

【问题讨论】:

    标签: java inputstream httpserver simplehttpserver get-request


    【解决方案1】:

    你应该关闭HttpExchange

    还请注意,您使用available() 的方式很棘手。它返回

    估计可以读取的字节数...

    和:

    请注意,虽然 {@code InputStream} 的某些实现会返回 流中的字节总数,很多不会。它是 永远不要正确使用这个方法的返回值来分配 用于保存此流中所有数据的缓冲区。

    完整示例(不完全是您的用例,但它回答了您的问题):

    /**
     * To test: 
     * 
     * ```` bash
     * $ curl -v -H "Content-Type: application/json" \
     *   -d '{"name":"Testing!"}' http://localhost:8000
     * ````
     */
    public static void main(String[] args) throws IOException {
        // Creates a basic HTTP server, with default Executor and system default socket
        // backlog (second parameter in create method, 0)
        final HttpServer server = HttpServer.create(
            new InetSocketAddress("localhost", 8000), 0);
        // context MUST start with "/". Root context is just "/"
        // HttpHandler implemented as lambda, note that HttpHandler#handle() throws an
        // IOException, so no need to catch it
        server.createContext("/", (he) -> {
            try {
                System.out.println(he.getRequestURI());
                final InputStream in = he.getRequestBody();
                final OutputStream out = he.getResponseBody();
    
                // first send header, than response body, if any
                // use default buffer size suited for your use case
                final byte[] buffer = new byte[in.available() == 0 ? 1024 : in.available()];
                System.out.println("buffer size=" + buffer.length);     
    
                // preferrable, specify *exact* size of response body. If not known, use 0
                // < HTTP/1.1 200 OK
                // < Date: Thu, 21 Jul 2016 08:14:25 GMT
                // < Transfer-encoding: chunked
    //            he.sendResponseHeaders(200, 0);
    //            int length;
    //            while ((length = in.read(buffer, 0, buffer.length)) >= 0) {
    //                out.write(buffer, 0, length);
    //            }
    
                // better way of doing it: buffer response body and set content length
                // < HTTP/1.1 200 OK
                // < Date: Thu, 21 Jul 2016 08:11:40 GMT
                // < Content-length: 19
                final ByteArrayOutputStream baos = new ByteArrayOutputStream(buffer.length);
                int length;
                while ((length = in.read(buffer, 0, buffer.length)) >= 0) {
                    baos.write(buffer, 0, length);
                }
                he.sendResponseHeaders(200, baos.size());
                baos.writeTo(out); // no need to close() of flush() ByteArrayOutputStream
    
            } finally {
                // Essential: HttpExchange must be closed
                he.close();
            }
        });
        server.start();
    }
    

    【讨论】:

    • 什么意思?什么时候关闭?
    • 关闭HttpExchange是什么意思?什么时候关门?
    • 谢谢,这很有帮助。我有另一个问题。是否可以从服务器端保持连接(持久连接)还是必须来自客户端?
    • 在示例中,连接仍然有效(参见 curl 输出):Connection #0 to host localhost left intact。顺便说一句,对于新问题,请发布一个新问题。在 cmets 中不要问其他问题(SO 礼仪)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-24
    相关资源
    最近更新 更多