[英]DataReader of SocketStream for UWP App
我已經看到了一些與此類似的問題,但是到目前為止,我還沒有看到適用於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);
我不知道我會從設備中獲得多少數據,我無法控制設備通信(除了請求信息外)。 我想我在尋找解決方案時已經閱讀了一半的網頁,但是找不到與該特定問題直接相關的任何內容。
因此,主要的問題是“您應該如何從套接字流中讀取數據,然后在沒有更多數據的時候(此時),只需返回當前流中的內容即可。緩沖區中可能還有剩余大小等待中被閱讀。
救命...
我不知道我會從設備中獲得多少數據,我無法控制設備通信(除了請求信息外)。 因此,主要的問題是“您應該如何從套接字流中讀取數據,然后在沒有更多數據的時候(此時),只需返回當前流中的內容即可。緩沖區中可能還有剩余大小等待中被閱讀。
根據您的描述,我為您找到了解決方案:
首先,將輸入流的讀取選項設置為Partial 。
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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.