gpt4 book ai didi

c# - 异步 TcpClient 没有及时读取所有数据

转载 作者:行者123 更新时间:2023-11-30 22:19:03 24 4
gpt4 key购买 nike

如果没有来自服务器的大量数据,或者如果有大量数据并且我取消了 Thread.Sleep(500) 行的注释,下面的代码可以工作。然而,我不想使用 Thread.Sleep 行,但如果我删除它,程序将在从服务器读取所有数据之前完成。问题似乎是 EndRead() 在读取所有数据之前不会阻塞,这是可以理解的,应该通过对 ReceiveCallback 的递归调用来解决,但事实并非如此。

我有一个在 Linux 上使用 C/C++ 编写的工作客户端。我试图让它与 c# 和 .Net 一起工作。我在 Linux 上使用 MonoDevelop 和 .Net 4.0。非常感谢有关如何解决此问题的任何帮助。

cli.send("command");
// Thread.Sleep(500);
cli.receive();
Console.WriteLine("response: {0}", cli.Response);
    private Static ManualResetEvent recvEvt = new ManualResetEvent(false);

public static void receive() {
StateObject state = new StateObject();
try {
state.stream = client.GetStream();
state.stream.BeginRead(state.buffer, 0, state.bufferSize, new AsyncCallback(ReceiveCallback), state);
recvEvt.WaitOne();
recvEvt.Reset();
}
catch (ArgumentNullException ne) { errorMessage = ne.ToString(); }
catch (ArgumentException ae) { errorMessage = ae.ToString(); }
catch (ObjectDisposedException oe) { errorMessage = oe.ToString(); }
catch (InvalidOperationException ie) { errorMessage = ie.ToString(); }
catch (SocketException se) { errorMessage = se.ToString(); }
}


private static void ReceiveCallback(IAsyncResult ar) {
StateObject state = (StateObject)ar.AsyncState;
try {
int bytesRead = state.stream.EndRead(ar);
if (bytesRead > 0 ) {
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
response = state.sb.ToString();
if (state.stream.DataAvailable) {
state.stream.BeginRead(state.buffer, 0, state.bufferSize, new AsyncCallback(ReceiveCallback), state);
recvEvt.WaitOne();
recvEvt.Reset();
}else
recvEvt.Set();
}else
recvEvt.Set();
}
catch (ArgumentNullException ne) { errorMessage = ne.ToString(); }
catch (ArgumentException ae) { errorMessage = ae.ToString(); }
catch (ObjectDisposedException oe) { errorMessage = oe.ToString(); }
catch (InvalidOperationException ie) { errorMessage = ie.ToString(); }
catch (SocketException se) { errorMessage = se.ToString(); }
}

最佳答案

问题是应用程序无法确定有更多数据通过线路传入。它所知道的只是它是否收到了任何数据。 DataAvailable 会告诉您是否已收到可以从网络流中读取的数据。远程端尚未发送给您的数据以及它已发送但尚未通过网络传递给您的数据对于您的应用程序来说基本上是未知的。

您将不得不再次重复调用 BeginRead 直到您或远程端挂断。稍微简化的 ReceiveCallback 看起来像这样:

private static void ReceiveCallback(IAsyncResult ar) {
StateObject state = (StateObject)ar.AsyncState;
int bytesRead = state.stream.EndRead(ar);
if (bytesRead > 0 ) {
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
state.stream.BeginRead(state.buffer, 0, state.bufferSize, new AsyncCallback(ReceiveCallback), state);
} else {
response = state.sb.ToString();
}
}

一旦接收到数据或连接终止,回调将被调用。连接关闭后响应完成。

关于c# - 异步 TcpClient 没有及时读取所有数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15779889/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com