c# - StreamSocket : datareader. LoadAsync 无限等待,即使数据可用

标签 c# .net sockets windows-phone-8 windows-runtime

我的 Windows Phone 8 应用程序中有以下代码。

//connection code, done during app start
socket = new StreamSocket();
await socket.ConnectAsync(serverHostName, serviceName);
dataReader = new DataReader(socket.InputStream);
dataReader.InputStreamOptions = InputStreamOptions.Partial;
dataWriter = new DataWriter(socket.OutputStream);

建立连接后,我有另一个线程检查传入的网络数据包

await dataReader.LoadAsync(2048);
dataReader.ReadBytes(buffer);
----------

工作流程如下

  • 手机使用 socket.ConnectAsync 连接到服务器
  • 服务器响应初始消息(手机在 dataReader.LoadAsync 函数中正确接收此消息)
  • 手机现在发送“业务特定”请求
  • 服务器现在回复“业务特定”响应(问题出在这里。电话有时收不到服务器的回复)。

“工作状态”和“非工作状态”没有场景差异。

所以我尝试调试它。我为 dataReader.LoadAsync 设置了一个断点并看到执行在调用时无限等待。

为确保服务器正确发送数据,我在 Windows 手机模拟器中运行了该应用程序,并在 PC 中运行了 WireShark 网络分析器。我可以看到正在接收电话 IP 地址的数据包。

当套接字中有数据可供读取时,有人知道为什么 dataReader.LoadAsync 函数调用根本不返回吗?

最佳答案

我遇到了同样的问题。这对蓝牙 RFCOMM SPP 串行端口设备尤其不利,因为底层 Rfcomm 对象不提供设置 ReadTimeout 值的功能。 编辑:InputStreamOptions.Partial 选项似乎适用于 UWP Win10 平台,但它仅在您已经知道您期望的大量数据时才有用。否则它将无限期地等待最后一次调用。

当我在这些行下方的引用资料中找到使用 CancellationTokenSource 解决问题时,我几乎要放弃了

//connect your Windows.Devices.Bluetooth.Rfcomm.RfcommDeviceService 
// see the Bluetooth chat example
[...]
StreamSocket streamSocket      = new StreamSocket();  
await streamSocket.ConnectAsync(...); //connect to Bluetooth device

DataReader dataReader = new DataReader(inputStream); // to read from the stream

try
 {
    var timeoutSource   = new CancellationTokenSource(1000); // 1000 ms
    uint numberBytesToRead = 256;
    var data    = await dataReader.LoadAsync(numberBytesToRead).AsTask(timeoutSource.Token);
 }
catch (TaskCanceledException)
{
  // we will get here, and everything looks fine, but the problem is:
  // The underlying streamSocket is also closed!
  // we can not re-use the streamSocket. Any more calls to LoadAsync results in exceptions (something about the object being not assigned...)
  // we need to do a full   await streamSocket.ConnectAsync(...)  again, but that takes ~3 seconds.
}

所以这个方法只是一个蛮力,最后的超时尝试。

来自@mayu 的方法非常有效(serialDevice.ReadTimeout),但仅适用于类 Windows.Devices.SerialCommunication.Serial Device 的设备,但 Windows.Devices.Bluetooth.Rfcomm.RfcommDeviceService。不知道TCP/IP套接字的情况如何。

简而言之,RFCOMM SPP 蓝牙连接是否有任何可用的超时? 或者有什么方法可以提前知道 .LoadAsync(1) 是否会因为没有可用的新数据而阻塞?

MSDN 的这个人有完全相同的问题,但 MS 也不知道答案:https://social.msdn.microsoft.com/Forums/vstudio/en-US/71ea17d4-ca16-43c2-ab43-02d5301def3f/chow-to-set-timeout-on-streamsocketreadasync?forum=wpdevelop

引用资料:

In UWP StreamSocket, can I read data with timeout and leave the connection open if timeout elapses

https://social.msdn.microsoft.com/Forums/en-US/8a5c4fdc-28d6-4a22-8df6-bc519efeaa4d/how-to-control-the-timeout-for-reading-from-streamsocket?forum=winappswithcsharp

DataReader of SocketStream for UWP App

关于c# - StreamSocket : datareader. LoadAsync 无限等待,即使数据可用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25364646/

相关文章:

python - Python套接字发送意外的RST数据包

java - 如何在AsyncTask中启动客户端并连接到服务器?

c# - 如果本地(但未使用)变量是对对象的唯一强引用,那么符合标准的 C# 编译器能否优化掉它?

c# - 检查元素是否存在于 Selenium 中

.net - 在.Net中使用Scala有什么好处?

.net - VB.Net:从My.Resources动态选择图像

sockets - 监听套接字和客户端套接字的阻塞模式的最佳实践?

c# - Windows Search sql - 无法访问 System.Search.QueryFocusedSummary

c# - 更新到 dotnet 6 后,dotnet run 无法正常工作

c# - Entity Framework 中 Select 和 Where 之间的区别