- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 NetworkStream
和 TcpClient
。
首先我设置我的 tcp 客户端:
tcp = new TcpClient(AddressFamily.InterNetwork)
{ NoDelay = true, ReceiveTimeout = 5000};
我的主要数据接收循环:
while (true)
{
//read available data from the device
int numBytesRead = await ReadAsync();
Console.WriteLine($"{numBytesRead} bytes read"); //BP2
}
以及实际的TCP数据读取:
public Task<int> ReadAsync()
{
var stream = tcp.GetStream();
return stream.ReadAsync(InBuffer, 0, InBuffer.Length); //BP1
}
我将其连接到测试平台,让我可以手动发送数据包。通过设置断点和调试,我检查了 stream.ReadTimeout
从 tcp
中获取值 5000。
如果我频繁发送数据,一切都会按预期进行。 但是如果我不发送任何数据,5 秒后似乎什么也没有发生,没有超时。我看到断点 BP1
在调试器中被击中,但在我从测试平台发送数据之前,BP2
没有被击中。我可以让它等待一分钟或更长时间,它似乎只是在等待,但在一分钟后收到发送的数据,这似乎是不正确的行为。 5 秒后 某事 肯定会发生(据我所知是一个异常(exception))?
已经很晚了,所以我期待一些非常基本的东西,但有人能看出我的错误是什么和解决方案吗?
好的,所以当我对我正在使用的实际 .Net 版本进行 RTFM 时(有多少次我被默认为 .Net Core 3 的 MS 发现了,我确实说过它已经晚了)我在评论部分看到了读取超时
:
This property affects only synchronous reads performed by calling the Read method. This property does not affect asynchronous reads performed by calling the BeginRead method.
我现在不清楚我是否可以完全使用现代可等待调用来安全地读取套接字数据,并特别设置超时。除了超时外它都在工作,但我不确定给定的 ReadAsync
如何在 NetworkStream
中没有覆盖。我必须做一些丑陋的 hack 还是有一个简单的解决方案?
在我的例子中,5000 是我在断定存在问题之前预计不会收到数据的最长时间 - 该协议(protocol)没有 ping 机制,所以如果没有出现,我假设连接已断开。因此,认为具有 5000 毫秒超时的异步读取会很好而且整洁。
最佳答案
网络对象的超时值仅适用于同步 操作。例如,来自 the documentation :
This option applies to synchronous Receive calls only.
对于 Socket.ReceiveTimeout
、TcpClient.ReceiveTimeout
和 NetworkStream.ReadTimeout
,所有实现最终都会调用 SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, ...)
这反过来有效地调用 native setsockopt()
函数。来自 that documentation :
SO_RCVTIMEO
DWORD
Sets the timeout, in milliseconds, for blocking receive calls.
(强调我的)
底层 native API 中的这种限制是托管 API 中存在相同限制的原因。超时值不适用于网络对象上的异步 I/O。
您需要自己实现超时,方法是在超时发生时关闭套接字。例如:
async Task<int> ReadAsync(TcpClient client, byte[] buffer, int index, int length, TimeSpan timeout)
{
Task<int> result = client.GetStream().ReadAsync(buffer, index, length);
await Task.WhenAny(result, Task.Delay(timeout));
if (!result.IsCompleted)
{
client.Close();
}
return await result;
}
关于这个主题的其他变体可以在其他相关问题中找到:
NetworkStream.ReadAsync with a cancellation token never cancels
Cancel C# 4.5 TcpClient ReadAsync by timeout
关闭套接字实际上是您所能做的全部。即使对于同步操作,如果发生超时,套接字将不再可用。没有可靠的方法来中断读取操作并期望套接字保持一致。
当然,您可以选择在关闭套接字之前提示用户。但是,如果您要这样做,您将在应用程序架构的更高级别实现超时,这样 I/O 操作本身就根本不知道超时。
关于c# - 为什么 NetworkStream.ReadAsync 没有超时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62161695/
我不确定我是否遗漏了什么或者 SslStream 中确实存在设计缺陷(可能还有其他可以包装内部流的流类)。 考虑这个伪代码: MyStream { Task ReadAsync() { ...
一段时间以来我一直在思考这个问题(并且知道这很愚蠢)。 我正在下载带有显示正常的 ProgressBar 的文件,但如何从 ReadAsync 流中获取数据进行保存? public static re
如果您不输入任何输入,为什么下面的代码永远不会完成,为什么即使在取消标记被取消后它仍然响应按下的键? // Set up a cancellation token var cancellationSo
我有以下代码(_ns 是一个 NetworkStream) await GetResponse(_ns); btnSend.Enabled = true; private async Task Get
我有一个 C# TcpClient 来异步读取数据。简化代码如下: public async Task StartReading(CancellationToken token) { // T
我以前使用过串行端口及其原始方法,如 BytesToRead、Read 和 Write。据说这些是不可靠的,我有很多忙等待我试图切换到它的异步方法。 我需要使用 2 个不同的超时时间从串口读取数据。第
我正在尝试使用 NetworkStream.ReadAsync() 来读取数据,但我找不到如何在调用后取消 ReadAsync()。对于背景,NetworkStream 由连接的 BluetoothC
当使用“SocketAsyncEventArgs”类和 ReadAsync 时,我应该将读取缓冲区放在哪里以及将发送缓冲区放在哪里?或者我只能一次阅读或发送而不是两者?我有点困惑。 最佳答案 我认为您
我正在尝试将下面的类转换为延迟返回文件。 public class ObservableFile2 : IObservable { private readonly IObservable s
试一试。使用单个按钮和按钮单击事件的以下代码设置新的 Windows 窗体应用程序: private async void button1_Click(object sender, EventArgs
当 NamedPipeServer 流从管道中读取任何数据时,它不会对 CancellationTokenSource.Cancel() 使用react 这是为什么? 如何限制我在服务器中等待来自客户
我正在使用 NetworkStream 和 TcpClient。 首先我设置我的 tcp 客户端: tcp = new TcpClient(AddressFamily.InterNetwork
NetworkStream.ReadAsync 什么时候任务完成?一旦接收到指定长度的数据? 如果是,它会返回 0 吗?然后 CancellationToken可以用作 ReadTimeout ,这是
在samples for the Cosmos DB SQL API , Database.ReadAsync() 有多种用途这似乎没有做任何有用的事情。该方法文档中的第二个注释并没有真正说明它可能用
在samples for the Cosmos DB SQL API , Database.ReadAsync() 有多种用途这似乎没有做任何有用的事情。该方法文档中的第二个注释并没有真正说明它可能用
我正在尝试在 .net 中使用 SerialPort 类。 我选择让我的服务保持异步,所以我在 SerialPort.BaseStream 上使用异步方法。 在我的异步方法中,我将一个 byte[]
鉴于以下情况: using System; using System.IO; using System.Threading; using System.Threading.Tasks; namespa
当调用 SQL Server 执行实际需要时间的操作时,SqlDataReader.ReadAsync() 会为我同步运行。有没有办法强制它异步运行,或者是我在 Task.Run() 中调用它的唯一选
我可以创建一个 MobileServiceClient 和 GetTable()至InsertAsync ,并查看如何将我的模型插入到 Azure 中的 Easy Table 表中。但是当我 Read
我正在尝试构建具有持久 TCP 连接的可扩展 服务器应用程序。我使用的序列化库是同步的,将其转换为APM会造成很大的开销(我已经测试过了)。 数据包的格式始终是数据包 ID 的一个字节,后跟几个 he
我是一名优秀的程序员,十分优秀!