WebSocketConnection does not answer a client close frame
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 80/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- csharp
- Ambito
- backend, networking
Direzione di ricerca
Inizia in MaxLib.WebServer/WebSocket/WebSocketConnection.cs intorno alle righe 237-250, dove un close frame in arrivo imposta solo ReceivedCloseSignal e chiama ReceiveClose, e confrontalo con il percorso Close() esistente, che invia già la risposta che l'issue si aspetta. Traccia come il ciclo di ping e l'evento Closed vengono smontati in modo che la classe base possa chiudere la connessione da sola. Riproduci con il repro.csproj/Program.cs dell'issue (dotnet run, poi dotnet run -- reply); done significa che "close reply received: NormalClosure" e "Closed event raised" appaiono nell'esecuzione predefinita.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
When a client sends a close frame, WebSocketConnection only sets ReceivedCloseSignal and calls ReceiveClose
(WebSocketConnection.cs#L237-L250).
It never sends a close frame back, which RFC 6455 §5.5.1 requires.
As a result, the ping loop keeps running, Closed never fires, and WebSocketEndpoint<T> never removes or disposes the connection.
Every normal client disconnect leaks a connection unless the subclass calls Close() from its ReceiveClose override.
Expected: the library replies to the close frame itself and the connection shuts down.
Reproduction
repro.csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MaxLib.WebServer" Version="5.0.0" />
</ItemGroup>
</Project>
Program.cs:
using System.Net.WebSockets;
using MaxLib.WebServer;
using MaxLib.WebServer.WebSocket;
// Pass "reply" to call Close() from ReceiveClose (the workaround) for comparison.
var reply = args.Contains("reply");
var closed = new TaskCompletionSource();
using var server = new Server(new WebServerSettings(8099, 5000));
server.InitialDefault();
var ws = new WebSocketService();
ws.Add(new Endpoint(closed, reply));
server.AddWebService(ws);
server.Start();
using var client = new ClientWebSocket();
await client.ConnectAsync(new Uri("ws://127.0.0.1:8099/"), default);
await client.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, null, default);
var receive = client.ReceiveAsync(new byte[1024], default);
var first = await Task.WhenAny(receive, Task.Delay(TimeSpan.FromSeconds(5)));
Console.WriteLine(first == receive
? $"close reply received: {receive.Result.CloseStatus}"
: "no close reply within 5 s");
first = await Task.WhenAny(closed.Task, Task.Delay(TimeSpan.FromSeconds(30)));
Console.WriteLine(first == closed.Task
? "Closed event raised"
: "Closed event not raised within 30 s");
server.Stop();
class Endpoint(TaskCompletionSource closed, bool reply) : WebSocketEndpoint<Connection>
{
public override string? Protocol => null;
protected override Connection? CreateConnection(Stream stream, HttpRequestHeader header)
{
var connection = new Connection(stream, reply);
connection.Closed += (_, _) => closed.TrySetResult();
return connection;
}
}
class Connection(Stream stream, bool reply) : WebSocketConnection(stream)
{
protected override Task ReceiveClose(CloseReason? reason, string? info)
=> reply ? Close() : Task.CompletedTask;
protected override Task ReceivedFrame(Frame frame) => Task.CompletedTask;
}
Output of dotnet run:
no close reply within 5 s
Closed event not raised within 30 s
Output of dotnet run -- reply:
close reply received: NormalClosure
Closed event raised
- Lingua principale
- C#
- Stelle
- 1
- Fork
- 3
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di Garados007/MaxLib.WebServer
-
Reason-phrase table has misspelled entries (`Unathorized`, `Switching Protcols`, `Multiple Choises`)Forse già presa @Jah-yee l’ha presa 23 giorni fa. Apertabug severity:low
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
-
documentation good first issue severity:low
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 90/100
-
bug severity:low
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
-
bug severity:low
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
-
bug severity:low
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
Tutte le issue di Garados007/MaxLib.WebServer
Issue simili
-
.NET good first issue testing
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
HelloblueAI/HelloblueGK#311 ·
I maintainer di solito rispondono entro 1 giorno
-
needs-area-label
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
I maintainer di solito rispondono entro 2 giorni
-
State: Needs Discussion
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
getsentry/sentry-dotnet#5876 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
area-Extensions-FileSystem untriaged
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
dotnet/runtime#136989 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Library Request: highspyApertalibrary-request
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
QuantConnect/Lean#10034 ·
I maintainer di solito rispondono entro 1 giorno