1

stream.DataAvailable を使って終了かどうかを判断しようとしていますが、値が false になることがありますが、しばらくすると再び true になります。カウンターを設定して、このように記号 '>' で終了を判断する必要があります

int connectCounter = 0;

while (connectCounter < 1200)
{
    if (stream.DataAvailable)
    {
        while (stream.DataAvailable)
        {
            byte[] buffer = new byte[bufferSize];
            int flag = stream.Read(buffer, 0, buffer.Length);
            string strReadXML_t = System.Text.Encoding.Default.GetString(buffer);
            strReadXML = strReadXML + strReadXML_t.Replace("\0", string.Empty);       
        }

        if (strReadXML.Substring(strReadXML.Length - 1, 1).Equals(">"))
        {
            break;
        }
    }
    Thread.Sleep(100);
    connectCounter++;
}

それに対処する良い方法はありますか?ありがとう!

4

3 に答える 3

1

いくつかのオプションがあります。同期のブロッキング読み取りを使用することも、非同期 IO パターンを使用することもできます。

単純に stream.Read() を呼び出すと、呼び出しはブロックされ、データが利用可能になるまで (TCP タイムアウトまで) 永久に待機します。あなたはそれをしたくないようです。データが完全に読み取られるまで、最大で 120 秒 (1200ms * 100) 待ちます。

このようなもの:

private class AsyncState
{
    public NetworkStream ns;
    public ManualResetEvent e;
    public byte[] b;
    public String strReadXML;
}

public void Run()
{
    TcpClient client ;//= ...
    NetworkStream networkStream = client.GetStream();
    byte[] buffer = new byte[1024];

    var completedEvent = new ManualResetEvent(false);

    networkStream.BeginRead(buffer, 0, buffer.Length,
                            AsyncRead,
                            new AsyncState
                            {
                                b = buffer,
                                ns = networkStream,
                                e = completedEvent,
                                strReadXML = ""
                            });

    // do other stuff here. ...

    // finally, wait 120s for the reading to complete
    bool success = completedEvent.WaitOne(1200*100, false);
    if (!success)
    {
        client.Close();
    }
}


private void AsyncRead(IAsyncResult ar)
{
    AsyncState state = ar as AsyncState;
    int n = state.ns.EndRead(ar);
    if (n == 0)
    {
        // no more bytes to read
        // signal completion
        state.e.Set();
        return;
    }

    // state.buffer now contains the bytes read

    string s = System.Text.Encoding.Default.GetString(state.b);
    state.strReadXML = state.strReadXML + s.Replace("\0", string.Empty);

    if (state.strReadXML.EndsWith(">"))
    {
        // got the "end".  signal completion
        state.e.Set();
        return;
    }

    // read again
    state.ns.BeginRead(state.b, 0, state.b.Length, AsyncRead, state);
}
于 2010-03-18T11:26:37.503 に答える
0

送信アプリケーションを制御できますか? その場合は、送信アプリケーションを変更して をラップしNetworkStream、これBinaryWriterを使用.Write( string )して文字列の長さを送信し、次に文字列自体を送信できます。受信アプリケーションでは (上記のように) をラップしてNetworkStream、ストリームから長さを読み取り、正しい長さの文字列を読み取るBinaryReader呼び出しを行うことができます。.ReadString()

送信側アプリケーションを制御できない場合はstream.Read()、ストリームの最後に 0 が返されるため、呼び出しからの戻りを確認できますが、これには送信側アプリケーションがソケットを閉じている必要があります。

また、stream.Read()リクエストしたバイト数が返される保証はありません。返されるバイト数が少なくなる可能性があります。変数flagは実際には である必要があり、この変数をメソッドにbytesread渡す必要があります。bytesread.GetString

于 2010-03-18T11:29:41.317 に答える
0

非同期読み取りを試してください。
コールバックが呼び出されると、既存のデータ バッファーを読み取ってから再度呼び出すことができます BeginRead。そのため、さらに多くのデータを受信すると、コールバックが再度呼び出されます。

何かのようなもの:

void DataReceived(IAsyncResult result) ///I am not sure about the parameters.
{
   ///read data from  buffer
   networkstream.BeginRead(
                 buffer, 0, buffer.Length,
                 new AsyncCallback(DataReceived),
                 null);
}

これはかなりまともなアプローチだと思います。

于 2010-03-18T11:11:34.727 に答える