私はJava HTTPサーバーを書いています。サーバー全体が機能していて、スレッドを使用していると思いました。ただし、リクエストを 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();
}
私の Websocket クラスは Socket をラップするだけで、in と out を提供します。これを行ったのは、ソケットをモックアウトしてサーバーをテストできるようにするためです。
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 ごとに 2 つの要求が行われることです。1 つは要求されたページに対するもので、もう 1 つはファビコンに対するものです。ファビコンのリクエストが来ず、スレッドがハングすることがあるようです。
うまくいったときにコンソールに出力するデバッグ情報を次に示します。
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
リクエストが読み取られるたびに、「受信中」メッセージが出力されます。したがって、この場合、「受信中」メッセージが 2 回出力され、2 つの要求が着信し、2 つのものがレンダリングされました。しかし、その後、同じページが (ただし別の時間に) これを行います(約 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)
後続のすべてのエラーは、リクエスト文字列が null であるためです。しかし、リクエスト文字列が null である理由がわかりません。デバッグの方法すらわかりません。
誰か助けてくれませんか??
また、2 番目の要求文字列がすぐに届かない場合、ユーザーは新しい URL を要求でき、2 番目にハングしたプロセスが完了することに注意することも重要です (したがって、4 番目の要求 URL がハングするものになります)。そのため、ユーザーがリクエストを停止したときのみ、最後のリクエストで約 10 秒後にエラーが発生します。場合によっては、20 の異なるページをリクエストできますが、ページのリクエストを停止して数秒待った後にのみ、エラーが表示されます。私はこれが起こっていると思いますか?
アップデート:
リクエストごとの 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]);
}
}
アップデート:
メンターの助けを借りて、ここで何が起こっているのかをより理解できたと思います。彼の考えでは、リクエストが受信されると、ブラウザーはすぐに別のリクエストを開始して、次のリクエストの読み込み時間を短縮します。ページごとにページを読み込むことができるので、これはもっともらしく聞こえますが、最後のページが要求されてから約 10 秒後にエラーが発生します。現在、カスタム例外でこれを処理していますが、より良い解決策に取り組んでいます。みんな助けてくれてありがとう!