簡體   English   中英

用於UWP App的SocketStream的DataReader

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM