1

あい!

私はftpファイルリストを取得しようとしていますが、それを行う小さなライブラリをすでに取得しています。問題は、すべてのデータが受信されるまで Socket.Receive() 関数がブロックされないことです。その行にブレークポイントを設定すると、すべてのデータが受信されますが、そうしないと 38 バイトしかありません (約 380 になるはずです)。

コードは次のとおりです。

While True
    Dim bytes As Integer = cSocket.Receive(buffer, buffer.Length, SocketFlags.None)
    mes += ASCII.GetString(buffer, 0, bytes)
    If bytes < buffer.Length Then
        Exit While
    End If
End While

私が言ったように:ブレークポイントが .Receive 部分のある行に設定されている場合に機能します。1 つの余分なループを保証する回避策を使用できますが、それは非常に汚いようです。何か案は?

//編集: もう少し情報を追加させてください。どのくらいのデータが受信されるかわかりません。コードは、ftp サーバーからデータを受信する関数からのものです。メッセージが CRLF で終わったら停止できると思っていましたが、リストされている各ファイル間に CRLF があるため、停止できません。例: file1.textCRLFfile2.txtCLRFfile3.txtCRLF

receive を呼び出すと、一覧表示するファイルがさらにある場合でも、最後に CRLF を持つ 1 つのファイルしか返されないことがあります。したがって、この状態は私には不安定に見えます。

4

1 に答える 1

4

この場合、「すべてのデータ」とは正確にはどういう意味ですか? ソケットが閉じられるまで、常にさらに多くのデータが存在する可能性があります。ネットワーク スタックは、一部のデータが論理的に一緒に属していることを知りません。さまざまなサイズの IP パケットに分割されます (複雑なアルゴリズムによって決定されます)。

受信者としてのあなたにとって、これは、受信されているデータをチャンクで取得することを意味します。Receive必要なデータがすべて揃っていることがわかるまで、電話をかけ続ける必要があります。

MSDNのドキュメントから(強調鉱山):

接続指向の Socket を使用している場合、Receive メソッドは、サイズ パラメーターで指定されたバイト数まで、使用可能なデータをすべて読み取ります。

ブレークポイントを設定するときに異なる動作が見られる理由は、送信側がデータを送信している間、文字通りアプリケーションを一時停止しているためです。オペレーティング システムは、パケットを受信して​​、ある程度までバッファリングします。標準のバッファ サイズは 8192 バイトで、プロパティで変更できReceiveBufferSizeます。

コード

これはコードでどのように変換されますか? 受信する必要があるデータの量を実際に知っていると仮定すると、改善されたコードは次のようになります。

Dim bytesRemaining As Integer = Buffer.Length
Dim sb As New StringBuilder
While bytesRemaining > 0
    Dim bytes As Integer = cSocket.Receive(Buffer,
                                           bytesRemaining, SocketFlags.None)
    bytesRemaining -= bytes
    sb.Append(ASCII.GetString(Buffer, 0, bytes))
End While
mes = sb.ToString()

大量のバイトを受信しない場合は終了したくないため、ループ内の条件はなくなりました。読み取りを続けたいと考えています。bytesRemainingまだ受信されていないバイト数の実行中のカウントを保持します。

あなたの質問には関係ありませんが、mes文字列連結をStringBuilder. 多くの新しい文字列を作成する可能性があり、それらすべて (最後の文字列を除く) をガベージ コレクションする必要があります。

于 2013-04-18T13:28:50.400 に答える