我看到了一些类似于此的问题,但到目前为止,我还没有看到一个适用于UWP平台的实际解决方案。
我正在连接到网络上的一些UPnP设备,这些设备通过端口1255将JSON发回。我有最初的连接工作和发送请求,告诉设备发送给我一些信息。
StreamSocket socket;
using (socket = new StreamSocket())
{
hostName = new HostName("192.168.0.nnn");
await socket.ConnectAsync(hostName, "1255");
//Code that does the request for info
await this.read();
}
public async Task<String> read()
{
string runStr = "";
uint inBufferCnt = 0;
using (reader = new DataReader(socket.InputStream))
{
reader.InputStreamOptions = Windows.Storage.Streams.InputStreamOptions.ReadAhead;
reader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
reader.ByteOrder = Windows.Storage.Streams.ByteOrder.LittleEndian;
inBufferCnt = await reader.LoadAsync(256); //InBuffer is always 256,
//even if there is more data waiting. If I put a task.delay in it will always return 256
while (reader.UnconsumedBufferLength > 0)
{
var iRead = reader.ReadString(reader.UnconsumedBufferLength);
runStr = runStr + iRead;
inBufferCnt = await reader.LoadAsync(64); //always hangs here.
//Even if I reduce to 1, it will sit waiting for new data
}
...直到最后一次LoadAsync为止,一切都很顺利。当流中有数据时,只要它小于64个字节,它就会在While循环周围旋转。如果比这个少,那么它只是坐在那里等待更多的数据。因此,缓冲区中可能有50个字节,我无法得到。在上面,inBufferCnt总是传递给LoadAsync的值的确切大小。
我一直在尝试各种事情,比如添加一个超时,但是在异常触发之后,我无法访问任何有用的东西,所以我仍然不知道流中有多少数据。
CancellationTokenSource cts = new CancellationTokenSource();
cts.CancelAfter(5000);
...
inBufferCnt = await reader.LoadAsync(64).AsTask(cts.Token);我不知道我将从设备中得到多少数据,我对设备通信没有任何控制(除了请求信息)。我想我已经阅读了一半的网页,同时也在寻找解决方案,但我找不到任何与这个特定问题直接相关的东西。
因此,主要的问题是“您应该如何从套接字流读取,然后当没有更多的数据时(此时),只需返回当前流中的内容,缓冲区中可能还有任何大小等待读取。”
救命..。
发布于 2016-05-06 08:37:41
我不知道我将从设备中得到多少数据,我对设备通信没有任何控制(除了请求信息)。因此,主要的问题是“您应该如何从套接字流读取,然后当没有更多的数据时(此时),只需返回当前流中的内容,缓冲区中可能还有任何大小等待读取。”
根据你的描述,我为你找到了一个解决办法:
首先,将输入流的读取选项设置为分部。
reader.InputStreamOptions = Windows.Storage.Streams.InputStreamOptions.Partial;通过这样做,当一个或多个字节可用时,异步读取操作将完成。因此,异步读取操作在没有任何字节可用的情况下,只等待新数据,然后添加一个超时来处理上述情况。
CancellationTokenSource cts = new CancellationTokenSource();
cts.CancelAfter(5000);
...
inBufferCnt = await reader.LoadAsync(sizeToReadEachTime).AsTask(cts.Token);下面是我验证过的示例代码:
public async Task<String> read()
{
string runStr = "";
uint inBufferCnt = 0;
//size of bytes to load each time.
uint sizeToReadEachTime = 256;
CancellationTokenSource cts = new CancellationTokenSource();
//set timeout here.
cts.CancelAfter(5000);
using (reader = new DataReader(socket.InputStream))
{
//set the read options for the input stream to Partial.
reader.InputStreamOptions = Windows.Storage.Streams.InputStreamOptions.Partial;
reader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
reader.ByteOrder = Windows.Storage.Streams.ByteOrder.LittleEndian;
while (true)
{
try
{
//add a timeout for the asynchronous load operation.
inBufferCnt = await reader.LoadAsync(sizeToReadEachTime).AsTask(cts.Token);
runStr += reader.ReadString(inBufferCnt);
}
catch (System.Threading.Tasks.TaskCanceledException)
{
//load operation will get timeout only when there is no data available.
cts.Dispose();
break;
}
}
reader.DetachStream();
}
return runStr;
}https://stackoverflow.com/questions/37015649
复制相似问题