<!--
{
  "availability" : [

  ],
  "documentType" : "symbol",
  "framework" : "Event",
  "identifier" : "/documentation/Event/ServerSocket",
  "metadataVersion" : "0.1.0",
  "role" : "Class",
  "symbol" : {
    "kind" : "Class",
    "modules" : [
      "Event"
    ],
    "preciseIdentifier" : "s:5Event12ServerSocketC"
  },
  "title" : "ServerSocket"
}
-->

# ServerSocket

A listening TCP server socket built on a non-blocking file descriptor and an [`EventLoop`](/documentation/Event/EventLoop).

```
final class ServerSocket
```

## Overview

`ServerSocket` represents a socket that has already been `bind(2)`-ed to a local
address and `listen(2)`-ed on. It accepts incoming client connections through two
ergonomic shapes:

- ``doc://Event/documentation/Event/ServerSocket/accept()`` — awaits exactly one incoming connection and returns a connected
  ``doc://Event/documentation/Event/Socket``. Use this when your protocol is request/response and you want explicit
  control over when to service the next connection.
- ``doc://Event/documentation/Event/ServerSocket/connections`` — an `AsyncThrowingStream<Socket, Error>` that yields each accepted
  `Socket` as it arrives, until the stream is cancelled or errors. Use this for
  server loops like `for try await client in server.connections { ... }`.

Construct a `ServerSocket` via [`listen(port:backlog:loop:)`](/documentation/Event/Socket/listen(port:backlog:loop:)) or
[`listen(on:backlog:loop:)`](/documentation/Event/Socket/listen(on:backlog:loop:)); direct construction is not part of the public API.

### Cancellation

The `connections` stream does **not** currently propagate `Task` cancellation down
into the outstanding `accept` event registration. Cancelling the owning task
terminates the `for-try-await` loop in your code but leaves the libevent callback
registered until the next activity or until the `ServerSocket` is deallocated.
Workarounds: call [`close()`](/documentation/Event/ServerSocket/close()) explicitly to tear down the listener, or drop the
last strong reference so `deinit` runs. See [Production Considerations](/documentation/Event/ProductionConsiderations).

### Concurrency

Marked `@unchecked Sendable` to permit handoff of ownership across task boundaries.
Concurrent `accept()` calls or simultaneous iteration of [`connections`](/documentation/Event/ServerSocket/connections) from multiple
tasks are **undefined behavior** — libevent state is not locked, and the stored
descriptor is closed unilaterally in `deinit`. The single-owner-per-scope discipline
from [Production Considerations](/documentation/Event/ProductionConsiderations) applies.