2013-08-22 22 views
1

我正在写一个Java HTTP服务器。我认为整个服务器正在运行,它正在使用线程。但是,我意识到将请求读入BufferedReader的代码片段并不一致。BufferedReader不一致地挂在我的套接字的输入流上

这里是读取传入的请求的代码:

private String receive(WebSocket webSocket) throws IOException { 
    int chr; 
    System.out.println("Receiving!"); 
    StringBuffer buffer = new StringBuffer(); 

    while ((chr = webSocket.in().read()) != -1) { 
    buffer.append((char) chr); 
    if (!webSocket.in().ready()) 
     break; 
    } 
    return buffer.toString(); 
} 

我的网页套接字类只是包装Socket和提供了一种在和出。我这样做,以便我可以嘲笑插座并测试我的服务器。

WebSocket的类看起来是这样的:

package http.server.socket; 

import java.io.*; 
import java.net.Socket; 

public class SystemSocket implements WebSocket { 
    private Socket theConnection; 
    private BufferedReader in; 
    private OutputStream out; 

    public SystemSocket(Socket theConnection) throws IOException { 
    this.theConnection = theConnection; 
    in = new BufferedReader(new InputStreamReader(theConnection.getInputStream())); 
    out = new BufferedOutputStream(theConnection.getOutputStream()); 
    } 

    public BufferedReader in() throws IOException { 
    return in; 
    } 

    public OutputStream out() throws IOException { 
    return out; 
    } 

    public void close() throws IOException { 
    in.close(); 
    out.close(); 
    theConnection.close(); 
    } 
} 

的问题是,与每个URL用户在浏览器中输入,两个请求是由 - 一个请求的页面,另一个用于图标。有时 - 看起来 - favicon的请求没有进入,线程挂起。

这是我必须打印到控制台一些调试信息,当事情右

Receiving! 
Receiving! 
REQUEST STRING = GET /color_picker.html HT 
[20130821 20:29:23] REQUEST: http://localhost:5000/color_picker.html 
[20130821 20:29:23] PAGE RENDERED 
REQUEST STRING = GET /favicon.ico HTTP/1.1 
[20130821 20:29:23] REQUEST: http://localhost:5000/favicon.ico 
[20130821 20:29:23] PAGE RENDERED 

“接收”每当要求越来越阅读是越来越打印消息。所以,在这种情况下,“接收”消息被打印两次,两个请求进来,两件事情被渲染。但随后,在同一页(但在不同的时间)将做到这一点(后约10秒)

Receiving! 
Receiving! 
REQUEST STRING = GET /color_picker.html HTTP/1.1 
[20130821 20:41:25] REQUEST: http://localhost:5000/color_picker.html 
[20130821 20:41:25] PAGE RENDERED 
REQUEST STRING = 
Exception in thread "ServerThread" java.lang.ArrayIndexOutOfBoundsException: 1 
    at http.request.Parser.setRequestLineData(Parser.java:42) 
    at http.request.Parser.setRequestHash(Parser.java:27) 
    at http.request.Parser.parse(Parser.java:13) 
    at http.request.Request.get(Request.java:18) 
    at http.server.ServerThread.run(ServerThread.java:39) 

以后的所有错误都是因为请求字符串为空。但我无法弄清楚为什么请求字符串为空。我甚至无法弄清楚如何调试。

任何人都可以帮忙吗?

另外需要注意的是,如果第二请求字符串不马上来,用户可以请求一个新的URL,这将导致第二个挂起进程来完成(所以后来第四请求的URL会是什么挂起)。所以,只有当用户停止请求时,在大约10秒后的最后一次请求中,我会得到错误。有时我可以请求20个不同的页面,只有当我停止请求页面并等待几秒钟后,我才会看到一个错误。我认为这是发生了什么?

UPDATE:

%的要求,这里是setRequestLineData()方法:

private void setRequestLineData() { 
    requestHash = new HashMap<String, String>(); 

    if (requestLineParts.length == 3) { 
    requestHash.put("httpMethod", requestLineParts[0]); 
    requestHash.put("url", requestLineParts[1]); //line 42 
    requestHash.put("httpProtocol", requestLineParts[2]); 
    } 
    else { 
    requestHash.put("httpMethod", requestLineParts[0]); 
    requestHash.put("url", requestLineParts[1]); 
    requestHash.put("queryString", requestLineParts[2]); 
    requestHash.put("httpProtocol", requestLineParts[3]); 
    } 
} 

UPDATE:

我想我找到了更多关于到底是怎么回事在这里与我的导师的帮助。他的想法是,一旦收到请求,浏览器立即启动另一个请求,以减少下一次请求的加载时间。这听起来对我来说似乎合理,因为我可以一页接一页地加载页面,但是在请求最后一页之后只有大约10秒钟,我得到一个错误。目前,我正在处理这个与自定义异常,但我正在一个更好的解决方案。感谢所有的帮助家伙!

+1

'http.request.Parser'是你的课程吗?请向我们展示'setRequestLineData()'方法。 –

+0

请注意为什么downvote?如果你让我知道,我仍然可以帮忙。 –

+0

我没有让你失望@MarioRossi。抱歉。 – Kelly

回答

3

ready()对消息结束不是有效的测试。它只会告诉你是否有数据可以被读取而不被阻塞。 TCP不是面向消息的协议,它是一种字节流协议。如果你想要消息,你必须自己实现它们,例如作为行,长度值元组,长度值元组,序列化对象,XML文档,...

如果有任何正确的使用ready()(或available()),并且这不是其中之一。

+0

谢谢你,EJP。根据Java Docs,“底层流的就绪方法返回false,表示进一步的输入请求会阻塞。”看起来这个流是空的并且阻塞了。所以我正在使用该命令来打破它是否确实阻塞。我也尝试过在另一个while循环中检查ready()的while循环,但它不起作用。你有另外一个建议吗?我在正确的轨道上吗? – Kelly

+0

关键是阻塞与消息完成无关。你必须继续阅读,直到你有一个完整的信息,并准备好()不能帮你。如果获得竞争性消息涉及阻止,那就这样做。 – EJP

相关问题