0

JakartaCommonsHttpClientに問題があります。自分で作成したHttpServerが実際の要求を取得する前に、完全に空の要求が1つあります。それが最初の問題です。 最初の問題は解決されました。不要なURLConnectionが原因です! 2番目の問題は、httpリクエストの3行目または4行目以降にリクエストデータが終了する場合があることです。

POST / HTTP/1.1
User-Agent: Jakarta Commons-HttpClient/3.1
Host: 127.0.0.1:4232

デバッグには、AxisTCPMonitorを使用しています。そこにはすべて問題ありませんが、空のリクエストです。

ストリームの処理方法:

StringBuffer requestBuffer = new StringBuffer();

InputStreamReader is = new InputStreamReader(socket.getInputStream(), "UTF-8");

int byteIn = -1;
do {
    byteIn = is.read();
    if (byteIn > 0) {
        requestBuffer.append((char) byteIn);
    }
} while (byteIn != -1 && is.ready());

String requestData = requestBuffer.toString();

ストリームを処理する新しい方法を見つけました。すべてのヘッダーパラメーターを読み取り、投稿データの読み取りに「content-length」を使用します。

InputStream is = mySocket.getInputStream();
if (is == null) {
    return;
}
BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8"));

// Read the request line
// ...
// ...

// Parse the header
Properties header = new Properties();
if (st.hasMoreTokens()) {
    String line = in.readLine();
    while (line != null && line.trim().length() > 0) {
        int p = line.indexOf(':');
        header.put(line.substring(0, p).trim().toLowerCase(), line.substring(p + 1).trim());
        line = in.readLine();
    }
}

// If the method is POST, there may be parameters
// in data section, too, read it:
String postLine = "";
if (method.equalsIgnoreCase("POST")) {
    long size = 0x7FFFFFFFFFFFFFFFl;
    String contentLength = header.getProperty("content-length");
    if (contentLength != null) {
        try {
            size = Integer.parseInt(contentLength);
        } catch (NumberFormatException ex) {
        }
    }
    postLine = "";
    char buf[] = new char[512];
    int read = in.read(buf);
    while (read >= 0 && size > 0 && !postLine.endsWith("\r\n")) {
        size -= read;
        postLine += String.valueOf(buf, 0, read);
        if (size > 0) {
            read = in.read(buf);
        }
    }
    postLine = postLine.trim();
    decodeParms(postLine, parms);
}

リクエストの送信方法:

client.getParams().setSoTimeout(30000);

method = new PostMethod(url.getPath());
method.getParams().setContentCharset("utf-8");
method.setRequestHeader("Content-Type", "application/xml; charset=utf-8");
method.addRequestHeader("Connection", "close");
method.setFollowRedirects(false);

byte[] requestXml = getRequestXml();

method.setRequestEntity(new InputStreamRequestEntity(new ByteArrayInputStream(requestXml)));

client.executeMethod(method);

int statusCode = method.getStatusCode();

あなたの誰かがこれらの問題を問題を解決する方法を考えていますか?

アレックス

4

2 に答える 2

1

最初の問題についてはわかりませんが、2番目の問題はこれによるものだと思います:

} while (byteIn != -1 && is.ready());

送信者がデータを送信する速度が十分でない場合、受信者はis.ready()次のパケットが送信される前に呼び出しを行う可能性があります。これによりis.ready()戻りfalseが発生し、ループが停止します。

最小限の修正は、その行を次のように変更することです。

} while (byteIn != -1);

編集

しかし実際には、@simonlord の回答に沿ってメソッドを書き直す必要があります。バッファリングされていないストリームを一度に 1 バイトずつ読み取るのは、非常に悪い考えです。呼び出しごとにシステム コールを実行することになりreadますが、これは恐ろしく非効率的です。

編集2

削除is.ready()によって遅延が発生した理由は、HTTP プロトコルに適切な注意を払っていなかったためです。問題は、HttpClient コードが TCP 接続の要求側を開いたままにして、接続を再利用できるようにすることでした。単純な (しかし最適ではない) 解決策は、接続の要求側を閉じるように HttpClient を構成することでした。あなたのコードは EOF をすぐに見たでしょう。あなたが実際にしたことは別の解決策でした。

率直に言って、HTTP 仕様全体を深く理解し、それを忠実に実装する準備ができていない限り、サーバー側の HTTP プロトコルを実装しようとするべきではありません。可能性として、既存の実装は、組み合わせて使用​​できるものよりも高速で信頼性が高くなります。仕様のサブセットを実装する際の問題は、サーバーが実装/テストする必要のない仕様の部分を使用する実際のブラウザーと通信する必要がある場合があることです。

于 2010-03-08T12:31:56.657 に答える
1

while ループの 2 番目の条件に関係している可能性があります。isReady() メソッドは、次の読み取りがブロックされる可能性があるときに false を返す可能性がありますが、ブロックするかどうかはあまり気にしないので、単純に削除できます (ここで詳細を読むことができます: http://java.sun.com/j2se/1.5.0/docs/api/java/io/InputStreamReader.html#ready%28%29 ). これに変更してみてください:

byte[] buf = new byte[500];
while((is.read(buf))>-1){
  requestBuffer.append(new String(buf).trim());
  buf = new byte[500];
}

これで、リクエスト全体を取得する必要があります。

于 2010-03-08T12:33:04.767 に答える