035
architectural distributed

Client-Server

Reference Wikipedia ↗
Client-Server — sequence diagram
Plate 035 sequence diagram

The Client-Server pattern is a distributed application structure that partitions tasks or workloads between providers of a resource or service, called servers, and requesters of that resource, called clients. It fundamentally separates concerns: clients focus on user interface and request logic, while servers focus on data storage, processing, and security. This separation allows for greater scalability, maintainability, and resource sharing.

Usage

The Client-Server pattern is ubiquitous in modern computing. It’s used in web applications (browsers as clients, web servers as servers), email systems (email clients like Outlook or Thunderbird, email servers like Exchange or Gmail), database systems (applications as clients, database management systems as servers), and file sharing (clients requesting files from a file server). It’s also a core principle in microservices architectures, where individual services act as servers providing specific functionalities to client applications. Cloud computing heavily relies on this pattern, with clients accessing resources and services hosted on remote servers.

Examples

  1. Web Browsers and Web Servers: A web browser (the client) requests a webpage from a web server (like Apache or Nginx). The server processes the request, retrieves the necessary HTML, CSS, and JavaScript files, and sends them back to the browser for rendering. This is a classic example of the Client-Server pattern.

  2. Database Applications and Database Servers: Applications like a customer relationship management (CRM) system (the client) interact with a database server (like MySQL, PostgreSQL, or Oracle). The CRM application sends queries to the database server to retrieve, update, or delete data. The database server handles the data management and returns the results to the application.

  3. Email Clients and Email Servers: An email client (like Outlook or Thunderbird) connects to an email server (like Exchange or Gmail’s IMAP/SMTP servers). The client sends requests to retrieve emails, send new emails, or manage folders. The server handles the email storage, routing, and delivery.

Specimens

15 implementations
Specimen 035.01 Dart View specimen ↗

The Client-Server pattern distributes application logic between servers providing resources or services and clients requesting those resources. This example uses Dart’s Isolate to simulate a simple server handling string reversal requests from clients. The server listens for messages on a ReceivePort, reverses the received string, and sends the result back via a SendPort provided by the client. This demonstrates asynchronous communication, a key aspect of client-server architectures. Dart’s isolates enable true concurrency, preventing blocking the main thread while processing requests, fitting the pattern’s need for responsiveness.

// server.dart
import 'dart:isolate';

void server(SendPort sendPort) {
  ReceivePort receivePort = ReceivePort();
  sendPort.send(receivePort.sendPort); // Send back the server's receive port

  receivePort.listen((message) {
    String input = message as String;
    String reversed = input.split('').reversed.join('');
    sendPort.send(reversed);
  });
}

// client.dart
import 'dart:isolate';

void main() async {
  Isolate.spawn(server, null);

  ReceivePort receivePort = ReceivePort();
  SendPort sendPort = receivePort.sendPort;
  Isolate spawnedIsolate = await Isolate.spawn(server, null);

  sendPort.post('hello');

  receivePort.listen((message) {
    print('Received from server: $message');
    spawnedIsolate.kill(); // Terminate isolate after receiving the result
    receivePort.close(); // Close the receiving port
  });
}