BufferReader 卡在 readline()

我正在为简单的 Http 请求和响应制作一个 HTTP 服务器和 HTTP Web 客户端。


这是服务器的代码


import java.io.*;

import java.net.*;

import java.util.*;


public final class WebServer{


public static void main(String[] args) throws Exception{

    //storing port number

    int port = 2048;


    //open socket and wait for TCP connection


    ServerSocket serverConnect = new ServerSocket(port);

    System.out.println("Server started.\nListening for connections on port : " + port + " ...\n");


        // we listen until user halts server execution

    while (true) {

        //Construct an object to process the HTTP request message. 

        //This will call another class where we do everything else

        HttpRequest request = new HttpRequest(serverConnect.accept());


        //create a new thread to process the request

        Thread thread = new Thread(request);

        thread.start();


    } //end of while


}//end of main

}//end of the class webServer


MMMHUHU
浏览 757回答 2
2回答

肥皂起泡泡

首先,您必须删除类中的行fis.close();(就在 之前os.close();)HttpRequest:如果不存在文件,则会引发此行,NullPointerException因为它fis为空,因此在向Not Found浏览器发送响应后,您的服务器不会关闭从该浏览器接受的套接字,那就是为什么即使您Not Found在浏览器中看到,您的请求也永远不会结束。其次,您的客户端卡住的原因是writeUTF()您用于发送请求标头的方法。似乎这一行out.writeUTF(CRLF);并没有真正发送空字符串,而是添加了一些其他与 UTF 相关的字符(您可能会在服务器的控制台输出中注意到这一点),因此您的服务器卡在while((headerLine = br.readLine()).length()!=0)等待客户端发送空字符串,但从未收到它。您需要替换out.writeUTF(CRLF);为out.writeBytes(CRLF);.此外,BufferedReader用于从套接字接收二进制文件也没什么意义。Reader通常与字符输入流一起使用,因此不适用于您的情况。您可以InputStream通过替换此片段来使用:String headerLine = null;     while((headerLine = br.readLine()).length()!=0){            System.out.println("asd"+headerLine);        }有了这个(我选择了 4096 的缓冲区大小,你可以用你喜欢的值替换它): int readBytes; byte[] cbuf = new byte[4096]; while((readBytes=inFromServer.read(cbuf, 0, 4096))>-1){        System.out.println("read: " + readBytes);    }注意:您可能很容易注意到这里不仅InputStream.read()会获取文件本身,还会获取statusLine,contentTypeLine和两个CRLFs,因此如果您想将它们与文件分开,您可以先读取它们,通过发出两个“readLines”然后仅通过以下方式获取文件read()

呼啦一阵风

在您的服务器中,您使用 writeBytes()将字符串作为字节序列写入底层输出流。通过丢弃其高八位,按顺序写出字符串中的每个字符。如果没有抛出异常,则写入的计数器增加 s 的长度。虽然您可能会担心非 ASCII 文本,但通常这正是您所需要的。在您的客户端中,您尝试使用 writeUTF()首先,两个字节被写入输出流,就像通过 writeShort 方法给出要跟随的字节数一样。该值是实际写出的字节数,而不是字符串的长度。在 length 之后,使用修改后的 UTF-8 字符编码按顺序输出字符串的每个字符。如果没有抛出异常,写入的计数器会增加写入输出流的总字节数。这将至少是 2 加上 str 的长度,至多是 2 加上 str 长度的三倍。虽然开头的 2 字节长度在其他情况下可能很有用,但这不是 Web 服务器所期望的,包括您的(这是正确的)。所以writeBytes()在你的客户端到处使用,它会突然起作用: out.writeBytes("GET /" +args[2] +" HTTP/1.1"); out.writeBytes(CRLF); out.writeBytes("Host: "+client.getLocalSocketAddress()); out.writeBytes(CRLF); out.writeBytes("Connection: close" + CRLF); out.writeBytes("User-agent: close" + CRLF); out.writeBytes(CRLF);事实上,这些额外的字节可能在您的服务器输出中可见,至少当我在 Eclipse 中运行它时,我看到了垃圾字符,作为神秘的空白空间和矩形中的一个小问号的组合(注意它们如何也出现在CRLF 单独发送时的行尾):(第一个请求是由 发出的writeUTF,第二个来自 Chrome)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java