denoland / deno

A modern runtime for JavaScript and TypeScript.
https://deno.com
MIT License
98.16k stars 5.4k forks source link

WebSocket leaves TCP connection open after calling close #25126

Open sergeysolovev opened 3 months ago

sergeysolovev commented 3 months ago

Version: Deno 1.45.5

Steps: start the server, start the client, wait for the client to call method close. Check the connections, I use ss -atn | grep 3333 on linux (can use lsof -i TCP:3333 on macos). I still see the tcp connection established and it’s still there several minutes after.

This looks unexpected to me. My use case - lets say there is some server issue so I wasn’t able to open a ws connection after a few seconds. I would keep trying to close and open another ws connection (with some delay). But that would keep leaking TCP connections.

LISTEN    0      128        127.0.0.1:3333         0.0.0.0:*           
ESTAB     0      0          127.0.0.1:45680      127.0.0.1:3333        
ESTAB     0      0          127.0.0.1:3333       127.0.0.1:45680      

Repro scripts

Server - establishes TCP connections and prints received data to stdout, does not implement web socket protocol

const listener = Deno.listen({
  hostname: '127.0.0.1',
  port: 3333,
  transport: 'tcp',
});

for await (const conn of listener) {
  console.log('connected');
  readLoop(conn);
}

async function readLoop(conn: Deno.TcpConn) {
  const buf = new Uint8Array(1024 * 1024);
  const decoder = new TextDecoder();

  while (true) {
    const nread = await conn.read(buf);
    if (nread === null) {
      console.log('eof');
      break;
    }
    const txt = decoder.decode(buf.slice(0, nread));
    console.log('read', txt);
  }

  conn.close();
}

Client - opens a websocket connection and closes it after 1 second regardless of the result.

const socket = new WebSocket('http://localhost:3333');

setTimeout(() => {
  socket.close();
  console.log('Called close');
}, 1000);
ariken74 commented 1 month ago

Hello, I experience a similar problem. WebSocket Server throws an "error" event "No response from ping frame" and then a "close" event is called. But I can still see the socket open on netstat. Client side (not implemented with Deno) nothing happens, the connection appear intact and the server still replies to websocket ping packets. The client can send data to the socket but on server side the "message" event is not called anymore.