StreamSocketListener 端口随机挂在 Windows IoT UWP 应用程序上
StreamSocketListener port randomly hangs on Windows IoT UWP application
我有一个我编写的 UWP 后台应用程序,它 运行s 在 Raspberry Pi 运行ning 最新版本的 Windows IoT 上。它的目的是处理 http 请求和 return 对多个移动应用程序的响应。
效果很好,只是套接字上的侦听端口似乎偶尔会挂起。后台应用程序的其余部分保持响应,所以我知道该应用程序仍在 运行ning。但是 http 请求停止响应。通常只需登录 IoT 仪表板并重新启动我的应用程序即可解决问题。但是我不明白为什么应用程序偶尔会挂起。
这是我认为相关的代码段:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using Windows.ApplicationModel.Background;
using Windows.Networking.Sockets;
namespace MyApp.Sandbox
{
public class SystemTest : IBackgroundTask
{
private StreamSocketListener listener = null;
public void Run(IBackgroundTaskInstance taskInstance)
{
StartServer();
}
public async void StartServer()
{
try
{
int port = 8189;
listener = new StreamSocketListener();
var currentSetting = listener.Control.QualityOfService;
listener.Control.QualityOfService = SocketQualityOfService.LowLatency;
await listener.BindServiceNameAsync(port.ToString());
listener.ConnectionReceived += async (sender, args) =>
{
var request = new StringBuilder();
using (var input = args.Socket.InputStream.AsStreamForRead())
{
int maxBuffer = 8192;
int index = 0;
List<byte> line = new List<byte>();
int b;
while (true)
{
try
{
b = input.ReadByte();
line.Add((byte)b);
if (b == 10 && line.Count >= 2)
{
if (line[line.Count - 2] == 13 && line[line.Count - 1] == 10)
{
byte[] byteArray = line.ToArray();
var dataString = Encoding.UTF8.GetString(byteArray, 0, byteArray.Length);
request.Append(dataString);
line = new List<byte>();
if (request.ToString().StartsWith("GET"))
{
break;
}
if (request.ToString().StartsWith("POST") &&
request.ToString().Contains(Environment.NewLine + Environment.NewLine))
{
string contentLength = GetValueFromHeader("Content-Length", request.ToString());
if (!contentLength.Equals(""))
{
int length = Convert.ToInt32(contentLength);
if (length > 0)
{
byteArray = new byte[length];
input.Read(byteArray, 0, length);
dataString = Encoding.UTF8.GetString(byteArray, 0, byteArray.Length);
request.Append(dataString);
}
}
break;
}
}
}
index++;
if (index > maxBuffer)
{
break;
}
}
catch
{
break;
}
}
input.Dispose();
}
using (var output = args.Socket.OutputStream)
{
using (var response = output.AsStreamForWrite())
{
var requestLines = request.ToString().Split(' ');
var url = requestLines.Length > 1 ? requestLines[1] : string.Empty;
string postLine = null;
if (requestLines.Length > 0)
{
if (requestLines[0] == "POST")
{
postLine = requestLines[requestLines.Length - 1];
}
}
string str = null;
try
{
// handle response here which fills "str"
}
catch (Exception innerEx)
{
Debug.WriteLine(innerEx.Message);
Debug.WriteLine(innerEx.StackTrace);
}
var html = Encoding.UTF8.GetBytes(str);
using (var bodyStream = new MemoryStream(html))
{
var header = $"HTTP/1.1 200 OK\r\nContent-Length: {bodyStream.Length}\r\nContent-Type: application/json\r\ncharset: UTF-8\r\nConnection: close\r\n\r\n";
var headerArray = Encoding.UTF8.GetBytes(header);
await response.WriteAsync(headerArray, 0, headerArray.Length);
await bodyStream.CopyToAsync(response);
await response.FlushAsync();
}
}
output.Dispose();
}
};
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
Debug.WriteLine(ex.StackTrace);
}
}
}
}
我已确认在我的构建配置中启用了 "Compile with .NET Native Toolchain"。我正在 运行 在发布模式下使用它。
我不确定是否需要做一些不同的事情来释放传入连接?是不是因为同时有多个请求,无法处理而挂了?
这是端口(在本例中为 8081)挂起时 netstat 的示例:
TCP 192.168.1.190:8081 5.101.0.209:32880 CLOSE_WAIT
TCP 192.168.1.190:8081 5.101.0.209:33494 CLOSE_WAIT
TCP 192.168.1.190:8081 5.101.0.209:60412 CLOSE_WAIT
TCP 192.168.1.190:8081 Mike-PC:59879 CLOSE_WAIT
TCP 192.168.1.190:8081 Mike-PC:59880 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43096 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43110 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43114 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43120 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43130 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43742 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43744 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43750 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43822 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43914 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43986 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:48646 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:48648 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:48702 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:48724 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:48774 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:48776 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:48820 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:48834 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:48918 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:49036 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:49058 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:49284 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:49416 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:49672 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:49680 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:50360 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:50566 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:50718 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:50724 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:50734 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:50938 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:51082 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:51524 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:51880 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:51946 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:52146 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:52212 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:52224 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:52310 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:53126 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:53206 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:53284 CLOSE_WAIT
TCP 192.168.1.190:8081 192.227.118.82:1550 ESTABLISHED
TCP 192.168.1.190:59613 52.242.211.89:https ESTABLISHED
TCP [::]:22 myapp:0 LISTENING
TCP [::]:135 myapp:0 LISTENING
TCP [::]:445 myapp:0 LISTENING
TCP [::]:5985 myapp:0 LISTENING
TCP [::]:8080 myapp:0 LISTENING
TCP [::]:8081 myapp:0 LISTENING
TCP [::]:47001 myapp:0 LISTENING
TCP [::]:49664 myapp:0 LISTENING
TCP [::]:49665 myapp:0 LISTENING
TCP [::]:49667 myapp:0 LISTENING
UDP 0.0.0.0:123 *:*
UDP 0.0.0.0:5050 *:*
UDP 0.0.0.0:5353 *:*
UDP 0.0.0.0:5355 *:*
UDP 0.0.0.0:29819 *:*
UDP 0.0.0.0:51049 *:*
UDP [::]:123 *:*
UDP [::]:5353 *:*
UDP [::]:5355 *:*
在这一点上,如果其他人 运行 遇到类似情况,我愿意接受建议....
谢谢!
您可以尝试添加 StreamSocket.Dispose 方法来中止任何挂起的操作并释放与 StreamSocket 对象关联的所有非托管资源。
listener.Control.KeepAlive = true;
listener.ConnectionReceived += async (sender, args) =>
{
//Your codes
args.Socket.Dispose();
};
我有一个我编写的 UWP 后台应用程序,它 运行s 在 Raspberry Pi 运行ning 最新版本的 Windows IoT 上。它的目的是处理 http 请求和 return 对多个移动应用程序的响应。
效果很好,只是套接字上的侦听端口似乎偶尔会挂起。后台应用程序的其余部分保持响应,所以我知道该应用程序仍在 运行ning。但是 http 请求停止响应。通常只需登录 IoT 仪表板并重新启动我的应用程序即可解决问题。但是我不明白为什么应用程序偶尔会挂起。
这是我认为相关的代码段:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using Windows.ApplicationModel.Background;
using Windows.Networking.Sockets;
namespace MyApp.Sandbox
{
public class SystemTest : IBackgroundTask
{
private StreamSocketListener listener = null;
public void Run(IBackgroundTaskInstance taskInstance)
{
StartServer();
}
public async void StartServer()
{
try
{
int port = 8189;
listener = new StreamSocketListener();
var currentSetting = listener.Control.QualityOfService;
listener.Control.QualityOfService = SocketQualityOfService.LowLatency;
await listener.BindServiceNameAsync(port.ToString());
listener.ConnectionReceived += async (sender, args) =>
{
var request = new StringBuilder();
using (var input = args.Socket.InputStream.AsStreamForRead())
{
int maxBuffer = 8192;
int index = 0;
List<byte> line = new List<byte>();
int b;
while (true)
{
try
{
b = input.ReadByte();
line.Add((byte)b);
if (b == 10 && line.Count >= 2)
{
if (line[line.Count - 2] == 13 && line[line.Count - 1] == 10)
{
byte[] byteArray = line.ToArray();
var dataString = Encoding.UTF8.GetString(byteArray, 0, byteArray.Length);
request.Append(dataString);
line = new List<byte>();
if (request.ToString().StartsWith("GET"))
{
break;
}
if (request.ToString().StartsWith("POST") &&
request.ToString().Contains(Environment.NewLine + Environment.NewLine))
{
string contentLength = GetValueFromHeader("Content-Length", request.ToString());
if (!contentLength.Equals(""))
{
int length = Convert.ToInt32(contentLength);
if (length > 0)
{
byteArray = new byte[length];
input.Read(byteArray, 0, length);
dataString = Encoding.UTF8.GetString(byteArray, 0, byteArray.Length);
request.Append(dataString);
}
}
break;
}
}
}
index++;
if (index > maxBuffer)
{
break;
}
}
catch
{
break;
}
}
input.Dispose();
}
using (var output = args.Socket.OutputStream)
{
using (var response = output.AsStreamForWrite())
{
var requestLines = request.ToString().Split(' ');
var url = requestLines.Length > 1 ? requestLines[1] : string.Empty;
string postLine = null;
if (requestLines.Length > 0)
{
if (requestLines[0] == "POST")
{
postLine = requestLines[requestLines.Length - 1];
}
}
string str = null;
try
{
// handle response here which fills "str"
}
catch (Exception innerEx)
{
Debug.WriteLine(innerEx.Message);
Debug.WriteLine(innerEx.StackTrace);
}
var html = Encoding.UTF8.GetBytes(str);
using (var bodyStream = new MemoryStream(html))
{
var header = $"HTTP/1.1 200 OK\r\nContent-Length: {bodyStream.Length}\r\nContent-Type: application/json\r\ncharset: UTF-8\r\nConnection: close\r\n\r\n";
var headerArray = Encoding.UTF8.GetBytes(header);
await response.WriteAsync(headerArray, 0, headerArray.Length);
await bodyStream.CopyToAsync(response);
await response.FlushAsync();
}
}
output.Dispose();
}
};
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
Debug.WriteLine(ex.StackTrace);
}
}
}
}
我已确认在我的构建配置中启用了 "Compile with .NET Native Toolchain"。我正在 运行 在发布模式下使用它。
我不确定是否需要做一些不同的事情来释放传入连接?是不是因为同时有多个请求,无法处理而挂了?
这是端口(在本例中为 8081)挂起时 netstat 的示例:
TCP 192.168.1.190:8081 5.101.0.209:32880 CLOSE_WAIT
TCP 192.168.1.190:8081 5.101.0.209:33494 CLOSE_WAIT
TCP 192.168.1.190:8081 5.101.0.209:60412 CLOSE_WAIT
TCP 192.168.1.190:8081 Mike-PC:59879 CLOSE_WAIT
TCP 192.168.1.190:8081 Mike-PC:59880 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43096 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43110 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43114 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43120 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43130 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43742 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43744 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43750 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43822 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43914 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:43986 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:48646 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:48648 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:48702 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:48724 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:48774 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:48776 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:48820 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:48834 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:48918 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:49036 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:49058 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:49284 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:49416 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:49672 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:49680 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:50360 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:50566 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:50718 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:50724 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:50734 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:50938 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:51082 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:51524 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:51880 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:51946 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:52146 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:52212 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:52224 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:52310 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:53126 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:53206 CLOSE_WAIT
TCP 192.168.1.190:8081 Galaxy-S20-5G:53284 CLOSE_WAIT
TCP 192.168.1.190:8081 192.227.118.82:1550 ESTABLISHED
TCP 192.168.1.190:59613 52.242.211.89:https ESTABLISHED
TCP [::]:22 myapp:0 LISTENING
TCP [::]:135 myapp:0 LISTENING
TCP [::]:445 myapp:0 LISTENING
TCP [::]:5985 myapp:0 LISTENING
TCP [::]:8080 myapp:0 LISTENING
TCP [::]:8081 myapp:0 LISTENING
TCP [::]:47001 myapp:0 LISTENING
TCP [::]:49664 myapp:0 LISTENING
TCP [::]:49665 myapp:0 LISTENING
TCP [::]:49667 myapp:0 LISTENING
UDP 0.0.0.0:123 *:*
UDP 0.0.0.0:5050 *:*
UDP 0.0.0.0:5353 *:*
UDP 0.0.0.0:5355 *:*
UDP 0.0.0.0:29819 *:*
UDP 0.0.0.0:51049 *:*
UDP [::]:123 *:*
UDP [::]:5353 *:*
UDP [::]:5355 *:*
在这一点上,如果其他人 运行 遇到类似情况,我愿意接受建议....
谢谢!
您可以尝试添加 StreamSocket.Dispose 方法来中止任何挂起的操作并释放与 StreamSocket 对象关联的所有非托管资源。
listener.Control.KeepAlive = true;
listener.ConnectionReceived += async (sender, args) =>
{
//Your codes
args.Socket.Dispose();
};