簡體   English   中英

StreamSocketListener在Raspberry Pi 3(IoT Core UWP)上從客戶端隨機接收到空

[英]StreamSocketListener randomly receive empty from client on Raspberry Pi 3 (IoT Core UWP)

我正在測試一個非常簡單的Web服務器代碼(可以從MSDN示例中復制它,也可以從我忘記的地方復制),我正在Raspberry Pi 3 Model B上使用IoT Core v.10.0.16299.309運行它。 我做了一切正確的事情,包括在每個請求上都放置了套接字,並且代碼在大多數情況下都起作用。

我只有一個客戶端,每30秒向此Web服務發送3個非常簡單的HTTP GET請求,只是一個簡單的URL,如下所示: http:// serverIP / get?id = 123它在小時內正確但隨機地返回結果,由於某些奇怪的原因,請求對象為空。 我不知道為什么。

private StreamSocketListener _listener;
private int _bufferSize = 8192;

public async void Run(IBackgroundTaskInstance taskInstance)
{
    taskInstance.GetDeferral();
    _listener = new StreamSocketListener();
    _listener.ConnectionReceived += HandleRequest;
    await _listener.BindServiceNameAsync("9080");       
}

public async void HandleRequest(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
  try 
  {
    StringBuilder request = new StringBuilder()
    using (IInputStream input = args.Socket.InputStream)
    {
         byte[] data = new byte[_bufferSize];
         IBuffer buffer = data.AsBuffer();
         uint bytesRead = _bufferSize;
         while (bytesRead == _bufferSize)
         {
            await input.ReadAsync(buffer, _bufferSize, InputStreamOptions.Partial);                        
            request.Append(Encoding.UTF8.GetString(data, 0, data.Length));
                    bytesRead = buffer.Length;

             // Some other code here to process the request object
             // and respond it back to the client. They are irrelevant.

          } // while
      } // using
   } // catch
   catch (Exception ex)
   {
      // Log here
   }
   finally 
   { 
       args.Socket.Dispose();
   }
} // method

我以為線程有問題,所以我禁用了大多數異步並等待。 有趣的是,結果是更好的。 請求對象是99%的罰款。 在12小時內,只有3-4次請求為空。 我認為這不是正確的解決方案...但是我真的被這個方案卡住了,不知道為什么。 任何幫助表示贊賞。

private StreamSocketListener _listener;
private int _bufferSize = 8192;

public async void Run(IBackgroundTaskInstance taskInstance)
{
    taskInstance.GetDeferral();
    _listener = new StreamSocketListener();
    _listener.ConnectionReceived += HandleRequest;
    _listener.BindServiceNameAsync("9080");     // ** No "await"
}

 // ** No "async"
public void HandleRequest(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
  try 
  {
    StringBuilder request = new StringBuilder()
    using (IInputStream input = args.Socket.InputStream)
    {
         byte[] data = new byte[_bufferSize];
         IBuffer buffer = data.AsBuffer();
         uint bytesRead = _bufferSize;
         while (bytesRead == _bufferSize)
         {
            // ** No "await"
            input.ReadAsync(buffer, _bufferSize, InputStreamOptions.Partial);                        
            request.Append(Encoding.UTF8.GetString(data, 0, data.Length));
                    bytesRead = buffer.Length;

             // Some other code here to process the request object
             // and respond it back to the client. They are irrelevant.

          } // while
      } // using
   } // catch
   catch (Exception ex)
   {
      // Log here
   }
   finally 
   { 
       args.Socket.Dispose();
   }
} // method

IInputStream.ReadAsync()文檔提供了一些有趣的信息,這些信息可能會有所幫助:

始終從IAsyncOperationWithProgress(IBuffer,UInt32)返回的緩沖區中讀取數據。 不要假設輸入緩沖區包含數據。 根據實現的不同,讀取的數據可能會放置在輸入緩沖區中,或者可能會在其他緩沖區中返回。 對於輸入緩沖區,您不必實現IBuffer接口。 相反,您可以創建Buffer類的實例。

提供的緩沖區可能不包含數據。

您可以使用返回緩沖區並從中提取數據,也可以使用DataReader.ReadBuffer() (或您的情況下的DataReader.ReadString() )從流中獲取數據。

通常,使用DataReader從流中讀取數據比使用低級API更容易。

您的代碼成為

 byte[] data = new byte[_bufferSize];
 IBuffer buffer = data.AsBuffer();
 uint bytesRead = _bufferSize;
 while (bytesRead == _bufferSize)
 {
    var readFromStreamBuffer = await input.ReadAsync(buffer, _bufferSize, InputStreamOptions.Partial);
    var readBytes = readFromStreamBuffer.ToArray();            
    request.Append(Encoding.UTF8.GetString(readBytes, 0, readBytes.Length));
    bytesRead = readFromStreamBuffer.Length;
  }

或使用DataReader.ReadBuffer()

 byte[] data = new byte[_bufferSize];
 IBuffer buffer = data.AsBuffer();
 uint bytesRead = _bufferSize;
 var dataReader = new DataReader(input);
 while (bytesRead == _bufferSize)
 {
    await dataReader.LoadAsync(_bufferSize);

    var readFromStreamBuffer = dataReader.ReadBuffer();
    var readBytes = readFromStreamBuffer.ToArray();            
    request.Append(Encoding.UTF8.GetString(readBytes, 0, readBytes.Length));

    bytesRead = readFromStreamBuffer.Length;
  }

或使用DataReader.ReadString()

 byte[] data = new byte[_bufferSize];
 IBuffer buffer = data.AsBuffer();
 uint bytesRead = _bufferSize;
 var dataReader = new DataReader(input);
 dataReader.UnicodeEncoding  = UnicodeEncoding.Utf8;
 while (bytesRead == _bufferSize)
 {
    await dataReader.LoadAsync(_bufferSize);
    request.Append(dataReader.ReadString(dataReader.UnconsumedBufferLength));

    bytesRead = readFromStreamBuffer.Length;
  }

出於種種主意,我將代碼更改為改為使用Socket.InputStream.AsStreamForRead(),然后使用.ReadLineAsync()只是讀取第一行以進行測試。 它似乎很穩定,經過12個小時以上,沒有一個空的請求!!!

對於我所需要的,這實際上很好,因為我並沒有真正構建一個功能齊全的Web服務器,因此我不需要獲得完整的請求。 我需要做的就是獲取HTTP GET QueryString並將參數傳遞給Raspberry Pi的GPIO。

正如Vincent所建議的,.ReadAsync()具有一些非常有趣的行為。 我一定會再嘗試他的建議。

public async void HandleRequest(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
    string requestString;
    try
    { 
        Stream inStream = args.Socket.InputStream.AsStreamForRead();
        StreamReader reader = new StreamReader(inStream);
        requestString = await reader.ReadLineAsync();

         // Some other code here to process the request object
         // and respond it back to the client. They are irrelevant
    } // catch     
    catch (Exception ex)
    {
      // Log here
    }
    finally 
    { 
       args.Socket.Dispose();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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