AWS Spatial Computing Blog

WebSocket APIs: Showcasing a Practical Networking Solution

As a Spatial Computing Prototyping Architect at Amazon Web Services (AWS), I work in a variety of development environments with varying networking needs. When a near real-time bi-directional networking solution is required, I consider using WebSockets. Amazon API Gateway WebSocket APIs are a serverless managed WebSocket solution that can be used with a variety of clients including but not limited to web front ends, Node applications, or standalone applications built for a specific device or operating system.

In this blog, I will provide:

  • An introduction to API Gateway WebSocket APIs
  • A sample AWS Cloud Development Kit (AWS CDK) project to deploy a basic API Gateway WebSocket API
  • A sample Unity project that includes:
    • a Unity Component WebSocket client
    • an example WebSocket message crafting and parsing script
    • simple game logic using the WebSocket client component

Build with these sample projects to add WebSocket APIs to your projects.

Overview of Amazon API Gateway WebSocket APIs

If your application requires frequent two-way communication between the backend services and front-end client(s), a WebSocket connection could be a good choice. WebSockets provide a persistent connection for bi-directional communication. Clients can send messages to the backend, and the backend can send messages to connected clients. This form of networked communication works well for turn-based games, chat applications, and near real-time dashboards.

API Gateway WebSocket APIs use transmission control protocol (TCP), creating a reliable connection between the server and clients. The connection stays open until either the server or client initiates a disconnection.

Routes are defined during the WebSocket API configuration. When a client sends a request to the WebSocket API, a route selection expression is evaluated, determining the resultant action to perform. API Gateway WebSocket APIs have three reserved predefined routes: $connect,  $disconnect, and $default, however, custom routes can be created. From the route, the request object is passed to an integration, which can be of a variety of types, the most common being an AWS Lambda function.

More details about the features and implementation of API Gateway WebSocket APIs can be found in the Working with WebSocket APIs developer guide. It is worth noting certain properties of WebSocket APIs, such as the connection duration of 2 hours, idle connection timeout of 10 minutes, message payload size of 128 KB (with a WebSocket frame size of 32 KB), and others listed in the documentation covering Amazon API Gateway quotas and important notes.

Overview of Sample Code

This GitHub repository contains sample AWS CDK code that deploys an API Gateway WebSocket API. The repository also contains Unity code for a sample application that connects as a client to the deployed WebSocket API.

Prerequisites

To deploy the sample code, make sure that you have the following configured:

Amazon API Gateway WebSocket API AWS CDK Sample

The sample AWS CDK code deploys an API Gateway WebSockets API with the following routes:

  • $connect – handles client connections
  • $default – default route that doesn’t perform any function
  • heartbeat – prevents idle timeout by keeping the connection alive
  • message – handles client messages to other connected clients
  • $disconnect – handles client disconnections

As shown in the architecture diagram below, each route has a Lambda function integration which receives the request information and performs an action.

Architecture diagram for the API Gateway WebSocket API

Connection state is maintained inside a DynamoDB table. When a client connects via the $connect route, the Lambda integration is executed and the connection ID is stored in the table. When a client disconnects, the $disconnect Lambda integration is executed and the connection ID is removed from the table. When a client sends a message to the message route, the Lambda integration retrieves all connection IDs from the DynamoDB table and broadcasts the message to all other connected clients. If a faster connection to DynamoDB is required for your use case, Amazon DynamoDB Accelerator (DAX) is a highly available caching service for DynamoDB, though for simplicity, DAX is not used for this sample project.

Follow the instructions in the AWS CDK project README.md to deploy the sample WebSocket API.

WebSocket Client Unity Sample

The sample Unity code is a simple WebSocket tag game where players cannot see each other’s avatar, but they get hints where the other players are moving. When a player actively tries to tag another player, their exact location is revealed to the other players, as shown in the animation below.

The left and right sides are separate instances of the WebSocket Tag game, each connected to the API Gateway WebSocket API. The player actions are passed via WebSocket messages.

When a player joins, their client connects to the WebSocket API. Messages are passed to the WebSocket API message route for the following player actions:

  • move – when a player moves, a nearby location is randomly selected and broadcast to other players
  • search – when a player tries to tag another player, the tagging player’s exact location is broadcast to other players
  • playerFound – when a player is tagged by another player, a message is broadcast to other players
  • playerSpawned – when a player joins the game, a message is broadcast to other players

The sample Unity project includes a Unity Component that contains the functionality and event hooks for a basic WebSocket client. Follow the instructions in the Unity project README.md to run the sample application.

Conclusion

This blog introduced you to API Gateway WebSocket APIs. It provided you with a reference to sample code to deploy a WebSocket API and build a game with basic WebSocket client functionality. The next time you need a persistent, bi-directional, near real-time networking solution without the burden of managing a server, give API Gateway WebSocket APIs a try.