我正在测试一个非常简单的Web服务器代码(从MSDN示例或我遗忘的地方复制它),我在带有IoT Core v.10.0.16299.309的Raspberry Pi 3 Model B上运行它。我做了一切正确的事情,包括在每个请求上配置套接字,代码大多数时间都在工作。
我只有一个客户端,每隔30秒就向这个Web服务发送3个非常简单的HTTP GET请求,只需要一个简单的URL:http://serverIP/get?id=123它会在一小时内正确返回结果,但请求对象是RANDOMLY由于一些奇怪的原因是空的。我无法弄明白为什么。
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
答案 0 :(得分:1)
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;
}
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;
}
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;
}
答案 1 :(得分:0)
出于想法,我更改了我的代码以使用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();
}
}