1

我尝试使用stream.DataAvailable来判断它是否完成,但有时该值是假的,但过了一会儿又是真的,我必须设置一个计数器并通过符号'>'判断结束像这样

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

尝试异步阅读
调用回调时,您可以读取现有数据缓冲区,然后 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 回答
0

您可以控制发送应用程序吗?如果这样做,您可以更改发送应用程序以将其包装NetworkStream在 a 中BinaryWriter并使用.Write( string )它将发送字符串的长度,然后是字符串本身。在接收应用程序(如上)中,您可以将NetworkStreamaBinaryReader和调用包装起来.ReadString(),它将从流中读取长度,然后为您读取正确的长度字符串。

如果您无法控制发送应用程序,那么您可以检查stream.Read()调用的返回,因为它在流结束时返回 0 - 尽管这将要求发送应用程序关闭套接字。

此外,stream.Read()不保证返回您请求的字节数,它可能返回更少。您的flag变量应该是bytesread,然后您应该将此bytesread变量传递给.GetString方法。

于 2010-03-18T11:29:41.317 回答