我正在尝试使用可以处理文本消息的 ASP.NET core 1.1 websocket 中间件构建一个 websocket 服务器。我的策略是使用固定大小的缓冲区来继续读取和解码,直到 websocket 消息结束。中间件设置如下:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
var logger = loggerFactory.CreateLogger("websocket");
app.UseWebSockets();
app.Use(async (http, next) =>
{
if (!http.WebSockets.IsWebSocketRequest)
{
await next();
return;
}
var websocket = await http.WebSockets.AcceptWebSocketAsync();
while (websocket.State == WebSocketState.Open)
{
var buffer = new ArraySegment<byte>(new byte[32]);
var charbuffer = new char[32];
try
{
var sb = new StringBuilder();
var decoder = Encoding.UTF8.GetDecoder();
//aha, we got a message
var detectResult = await websocket.ReceiveAsync(buffer, CancellationToken.None);
var receiveResult = detectResult;
while (!receiveResult.EndOfMessage)
{
var charLen = decoder.GetChars(buffer.Array, 0, receiveResult.Count, charbuffer, 0);
logger.LogInformation($"Decoded {charLen} byte(s) from wire");
sb.Append(charbuffer, 0, charLen);
receiveResult = await websocket.ReceiveAsync(buffer, CancellationToken.None);
}
var charLenFinal = decoder.GetChars(buffer.Array, 0, receiveResult.Count, charbuffer, 0);
logger.LogInformation($"Decoded {charLenFinal} byte(s) from wire");
sb.Append(charbuffer, 0, charLenFinal);
var message = sb.ToString();
logger.LogInformation($"decoded message: {message}");
await websocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes("got it")), WebSocketMessageType.Text, true, CancellationToken.None);
}
catch (Exception ex)
{
logger.LogError(ex.Message);
logger.LogError(ex.InnerException?.Message ?? string.Empty);
}
}
});
}
现在该代码适用于仅包含 ASCII 字符的文本。但是当我尝试发送长度大于缓冲区大小的 Unicode 文本消息(越南语)时,出现异常
fail: websocket[0]
The remote party closed the WebSocket connection without completing the close handshake.
fail: websocket[0]
at System.Net.WebSockets.ManagedWebSocket.<ReceiveAsyncPrivate>d__60.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at MvcApp.Startup.<>c__DisplayClass5_0.<<Configure>b__0>d.MoveNext()
异常发生在该行
var detectResult = await websocket.ReceiveAsync(buffer, CancellationToken.None);
此错误的原因可能是什么?