5

私は、ずっと避けてきたこの Web 全体に慣れるための演習として、非常に単純でかなり低レベルの HTTP (HTTP の一部) サーバーを作成しました。最初の試みとしてはかなりうまく機能します (実際に使用することを誰かに勧めるほどではありませんが、私が言ったことは実行します)。ここでの問題は、GET 操作が頻繁に失敗することです (更新は役立ちますが、あまり良くありません - 以下に詳細を示します)。

void start()
{
    //...
    try(ServerSocket webSock = new ServerSocket(47000) {
    //...
        while(running) {
           try {
               Socket sock = webSock.accept();
               //read/write from/to sock 
           }
           //...
           Thread.sleep(10);
        }
    } 
}

(完全なコードはこちら: http://pastebin.com/5B1ZuusH )

私はが間違っているのか正確にはわかりません。

エラーが発生します:

This webpage is not available
The webpage at http://localhost:47000/ might be temporarily down or it may have moved permanently to a new web address.
Error 15 (net::ERR_SOCKET_NOT_CONNECTED): Unknown error.

かなり (ページ全体が読み込まれない)、スクリプトや画像も読み込まれないことがあります。必要に応じて、コード全体を投稿できますが、残りはほとんどボイラープレートです。

4

1 に答える 1

5

[別の更新]

私の応答を明確にするのはOKです。これは、GETリクエストを読み取る方法を示す簡単なWebサーバーです。同じ接続で複数の要求を処理することに注意してください。接続が閉じられると、プログラムは終了します。通常、接続が閉じてプログラムが終了する前に、同じ Web ブラウザーから多数の要求を送信できます。これは、メッセージが終了したシグナルとしてストリームの終わりを使用できないことを意味します。

手書きの Web サーバーを実際の目的で使用することは決してないことに注意してください。私のお気に入りは Tomcat ですが、他のフレームワークも問題ありません。

public class MyWebServer
{
   public static void main(String[] args) throws Exception
   {
      ServerSocket server = new ServerSocket(47000);
      Socket conn = server.accept();
      BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));

      // don't use buffered writer because we need to write both "text" and "binary"
      OutputStream out = conn.getOutputStream();
      int count = 0;
      while (true)
      {
         count++;
         String line = reader.readLine();
         if (line == null)
         {
            System.out.println("Connection closed");
            break;
         }
         System.out.println("" + count + ": " + line);
         if (line.equals(""))
         {
            System.out.println("Writing response...");

            // need to construct response bytes first
            byte [] response = "<html><body>Hello World</body></html>".getBytes("ASCII");

            String statusLine = "HTTP/1.1 200 OK\r\n";
            out.write(statusLine.getBytes("ASCII"));

            String contentLength = "Content-Length: " + response.length + "\r\n";
            out.write(contentLength.getBytes("ASCII"));

            // signal end of headers
            out.write( "\r\n".getBytes("ASCII"));

            // write actual response and flush
            out.write(response);
            out.flush();
         }
      }
   }
}

【オリジンレスポンス】

HTTP リクエストをリッスンする適切な方法は何ですか?

私たちのほとんどにとって、適切な方法は、TomcatJetty、またはNettyなどの適切に設計された Web サーバー フレームワークを使用することです。

このウェブ全体に慣れるための練習として

ただし、これが HTTP について学習するための学術的な演習である場合は、最初に HTTP プロトコルを学習する必要があります ( http://www.w3.org/Protocols/rfc2616/rfc2616.htmlを参照)。GET 要求がいつ完了し、応答を送信するのが理にかなっているのかを把握するためにコードが開始行やヘッダーなどを識別しようとしないため、これを行っていないと確信しています。

[アップデート]

涼しい。TCP がストリーム指向であり、メッセージ境界を保持しないことについて学習しました。はい、アプリケーションはそれを処理する必要があります。readLineここに最終的な考えがあります -開始行とヘッダーを読んでいた場合は、おそらく GET リクエストに対してのみ、実験をかなり確実に機能させることができます。空白行を取得すると、リクエストは完了です。これにより、バッファリングされたリーダーが適切なタイミングでブロックされ、すべてのコンテンツが取得されます。

Content-Length ヘッダーを解析し、いくつかのバイト数を読み取る必要があるため、これは POST などでは機能しません。

うまくいけば、これを正しく確実に実行するためにどれだけの労力が必要かがわかったときに、この実験が Jetty をより高く評価するようになることを願っています。

于 2012-11-25T14:32:08.670 に答える