为什么scanner.hasNext()在读取Http Request时会阻塞

时间:2016-09-03 11:09:22

标签: java http

我正在编写一个接收http请求的服务器(只有GET方法作为学校简化的一部分)

我使用Socket类来获取连接 然后我使用InputStream以及Scanner来读取http请求。

然而,当我使用hasNext()逐行阅读http请求标题时。该程序挂起hasNext(),等待更多输入,即使它消耗了所有行。

以下是我的readRequest方法:

public void readRequest(Socket client) throws BadRequestException {
    StringBuilder builder = new StringBuilder();

    try {
        Scanner sc = new Scanner(client.getInputStream());
        sc.useDelimiter("\\r\\n");

        while(sc.hasNext()){
            builder.append(sc.next());
            builder.append("\n");
        }

        parseRequestFromClient(builder.toString());
    } catch (IOException e) {
        throw new BadRequestException(e.getMessage());
    }

2 个答案:

答案 0 :(得分:0)

您面临此问题,因为hasNext会在场景后面读取源,以检查是否有另一个匹配的令牌,直到源到达终点,方法是返回-1,这不是您的情况。< / p>

这里提醒的是方法hasNext的Javadoc:

  

如果此扫描器的输入中有另一个标记,则返回true。这个   方法可能会在等待输入时阻止进行扫描。扫描仪没有   超越任何输入。

你应该避免重新发明方向盘并使用一个能够为你做到的库,比如DavidWebb和其他许多人。

答案 1 :(得分:0)

根据rfc 7230(已废弃2616)从套接字读取字节。

Http请求必须使用7位usascii进行编码。 除了0x0a和0x0d之外,位7设置或小于0x20的任何字节都应该导致400错误请求。

读取直到0x0d 0x0a 0x0d 0x0a序列。

之后第一行是由0x0d 0x0a分隔的请求行,其余是标题行。

将请求行拆分为0x20,它应该正好返回3个部分。 其他任何事情都意味着某人正在攻击你的服务器,发送400状态。

标题应该拼接“:”恰好给出2个部分。其他任何东西发送400状态。 修剪(headerkey)!= headerkey 400状态。

只有在此之后,您才可以开始urldecode请求行[2]和标题值。

重复标头密钥? 400状态。 重复的请求参数? 400状态。

执行任何其他操作将导致服务器比已知的请求参与者和/或标题走私可以破解。

只有通过解释usascii 7位,你才能免受utf8黑客攻击 0x0a在usascii 7位中只有一个表示。但在utf8中有几个 0x0a 0x00a 0x000a 0x0000a 0x00000a 0x00000a 0x0000000a是一样的!

在进行任何编程之前阅读rfc 7230-7235!使你的服务器很难破解。