Skip to main content
On this page

TCP & UDP connections

The Deno.listen-API gives you low level access to handling TCP or UDP connections. If your use case is spinning up an HTTP server you should use Deno.serve instead.

Listening for a connection Jump to heading

In order to accept requests, first you need to listen for a connection on a network port.

const listener = Deno.listen({ port: 8080 });

Info

When supplying a port, Deno assumes you are going to listen on a TCP socket as well as bind to the localhost. You can specify transport: "tcp" to be more explicit as well as provide an IP address or hostname in the hostname property as well.

If there is an issue with opening the network port, Deno.listen() will throw, so often in a server sense, you will want to wrap it in a try ... catch block in order to handle exceptions, such as the port already being in use.

try {
  const listener = Deno.listen({ port: 8080 });
} catch (err) {
  // handle error
}

You can also listen for a TLS connection (e.g. HTTPS) using Deno.listenTls():

const server = Deno.listenTls({
  port: 8443,
  certFile: "localhost.crt",
  keyFile: "localhost.key",
  alpnProtocols: ["h2", "http/1.1"],
});

The certFile and keyFile options are required and point to the appropriate certificate and key files for the server. They are relative to the CWD for Deno. The alpnProtocols property is optional, but if you want to be able to support HTTP/2 on the server, you add the protocols here, as the protocol negotiation happens during the TLS negotiation with the client and server.

Handling connections Jump to heading

Once we are listening for a connection, we need to handle the connection. The return value of Deno.listen() or Deno.listenTls() is a Deno.Listener which is an async iterable which yields up Deno.Conn connections as well as provide a couple methods for handling connections.

To use it as an async iterable you would do something like this:

const server = Deno.listen({ port: 8080 });

for await (const conn of server) {
  // ...handle the connection...
}

Every connection made would yield a Deno.Conn assigned to conn. Then further processing can be applied to the connection.

There is also an .accept() method on the listener which can be used:

const server = Deno.listen({ port: 8080 });

while (true) {
  try {
    const conn = await server.accept();
    // ... handle the connection ...
  } catch (err) {
    // The listener has closed
    break;
  }
}

Whether using the async iterator or the .accept() method, exceptions can be thrown and robust production code should handle these using try ... catch blocks. When it comes to accepting TLS connections, there can be many conditions, like invalid or unknown certificates which can be surfaced on the listener and might need handling in the user code.

A listener also has a .close() method which can be used to close the listener.