← Назад к вопросам

Как происходит клиент серверное взаимодействие?

1.3 Junior🔥 241 комментариев
#REST API и HTTP#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Клиент-серверное взаимодействие

Клиент-серверная архитектура — это парадигма, где клиент отправляет запросы серверу, а сервер обрабатывает и возвращает ответы. Разберём это на всех уровнях абстракции.

1. Сетевой уровень (OSI Model)

Взаимодействие проходит через несколько слоёв:

# Layer 7 (Application) — HTTP/REST API
# Layer 4 (Transport) — TCP/UDP
# Layer 3 (Network) — IP адреса
# Layer 2 (Data Link) — MAC адреса
# Layer 1 (Physical) — электрические сигналы

import socket

# TCP сокет (Layer 4)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("example.com", 80))  # IP, Port
sock.send(b"GET / HTTP/1.1\r\n")  # HTTP request
response = sock.recv(4096)  # HTTP response
sock.close()

2. TCP/IP протокол трёхстороннего handshake

Перед передачей данных устанавливается соединение:

import socket

# Клиент инициирует SYN пакет
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("server.com", 443))

# За кулисами происходит:
# 1. Клиент → Сервер: SYN (seq=x)
# 2. Сервер → Клиент: SYN-ACK (seq=y, ack=x+1)
# 3. Клиент → Сервер: ACK (seq=x+1, ack=y+1)
# Теперь соединение установлено (ESTABLISHED)

print("TCP соединение установлено")
sock.close()

3. HTTP протокол (Request-Response)

import requests
from typing import Dict, Any

# HTTP запрос имеет структуру:
headers: Dict[str, str] = {
    "Host": "api.example.com",
    "User-Agent": "Python-Client/1.0",
    "Content-Type": "application/json",
    "Authorization": "Bearer token123"
}

body = {"name": "John", "age": 30}

# Запрос
response = requests.post(
    "https://api.example.com/users",
    json=body,
    headers=headers,
    timeout=10
)

# HTTP ответ имеет структуру:
print(f"Status Code: {response.status_code}")  # 200, 404, 500 и т.д.
print(f"Headers: {response.headers}")  # Content-Type, Set-Cookie и т.д.
print(f"Body: {response.json()}")  # Данные

# Request:
# POST /users HTTP/1.1
# Host: api.example.com
# Content-Length: 25
# Content-Type: application/json
#
# {"name":"John","age":30}

# Response:
# HTTP/1.1 201 Created
# Content-Type: application/json
# Content-Length: 40
#
# {"id":123,"name":"John","age":30}

4. Асинхронный REST API сервер

from fastapi import FastAPI, Request, HTTPException
from pydantic import BaseModel
import asyncio

app = FastAPI()

class UserCreate(BaseModel):
    name: str
    age: int

class UserResponse(BaseModel):
    id: int
    name: str
    age: int

# Сервер слушает входящие запросы
@app.post("/users")
async def create_user(user: UserCreate) -> UserResponse:
    # Сервер:
    # 1. Получает запрос
    # 2. Парсит JSON
    # 3. Валидирует данные (Pydantic)
    # 4. Обрабатывает логику
    # 5. Возвращает ответ
    
    # Имитация сохранения в БД
    await asyncio.sleep(0.1)
    
    return UserResponse(id=1, name=user.name, age=user.age)

@app.get("/users/{user_id}")
async def get_user(user_id: int) -> UserResponse:
    if user_id < 1:
        raise HTTPException(status_code=400, detail="Invalid ID")
    
    # Поиск пользователя
    return UserResponse(id=user_id, name="John", age=30)

5. WebSockets (двусторонняя коммуникация)

Для real-time данных используются WebSockets:

from fastapi import WebSocket, WebSocketDisconnect
from typing import List

class ConnectionManager:
    def __init__(self):
        self.active_connections: List[WebSocket] = []
    
    async def connect(self, websocket: WebSocket):
        await websocket.accept()
        self.active_connections.append(websocket)
    
    def disconnect(self, websocket: WebSocket):
        self.active_connections.remove(websocket)
    
    async def broadcast(self, message: str):
        # Отправить сообщение всем клиентам
        for connection in self.active_connections:
            await connection.send_text(message)

manager = ConnectionManager()

@app.websocket("/ws/chat")
async def websocket_endpoint(websocket: WebSocket):
    await manager.connect(websocket)
    try:
        while True:
            # Получить сообщение от клиента
            data = await websocket.receive_text()
            # Отправить всем подключённым клиентам
            await manager.broadcast(f"Message: {data}")
    except WebSocketDisconnect:
        manager.disconnect(websocket)

6. gRPC (альтернатива REST)

Для микросервисов с высокой производительностью:

import grpc
from concurrent import futures
from typing import Iterator

# .proto файл определяет контракт
class UserServicer:
    def GetUser(self, request, context):
        # Бинарный протокол (Protocol Buffers)
        # Быстрее и компактнее чем JSON
        return {"id": 1, "name": "John"}
    
    def StreamUsers(self, request, context) -> Iterator:
        # Server streaming — отправить много данных
        for i in range(100):
            yield {"id": i, "name": f"User {i}"}

# Запустить gRPC сервер
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
server.add_insecure_port("[::]:50051")
server.start()

7. Полный цикл взаимодействия

import requests
import time
from typing import Dict, Any

def client_server_cycle() -> None:
    # КЛИЕНТ отправляет запрос
    url = "https://api.example.com/users"
    payload = {"name": "Alice", "email": "alice@example.com"}
    
    # Шаг 1: DNS lookup
    # api.example.com → 93.184.216.34
    
    # Шаг 2: TCP handshake (три пакета)
    # Клиент → Сервер → Клиент
    
    # Шаг 3: TLS handshake (HTTPS)
    # Обмен сертификатами и ключами
    
    # Шаг 4: Отправка HTTP запроса
    start = time.time()
    response = requests.post(
        url,
        json=payload,
        timeout=30
    )
    elapsed = time.time() - start
    
    print(f"Response time: {elapsed:.3f}s")
    print(f"Status: {response.status_code}")
    print(f"Body: {response.json()}")
    
    # За кулисами на сервере:
    # 1. Получение пакета
    # 2. Парсинг HTTP заголовков и тела
    # 3. Маршрутизация к нужному обработчику
    # 4. Валидация данных
    # 5. Обработка бизнес-логики (БД, кэш и т.д.)
    # 6. Формирование ответа
    # 7. Отправка обратно клиенту

client_server_cycle()

8. Обработка ошибок и timeouts

import requests
from requests.exceptions import (
    Timeout,
    ConnectionError,
    HTTPError
)

def robust_request(url: str) -> Dict[str, Any] | None:
    try:
        response = requests.get(
            url,
            timeout=5,  # Timeout в 5 секунд
            retries=3   # Retry 3 раза
        )
        response.raise_for_status()  # Если 4xx или 5xx
        return response.json()
    
    except Timeout:
        print("Server took too long to respond")
        return None
    
    except ConnectionError:
        print("Failed to connect to server")
        return None
    
    except HTTPError as e:
        print(f"HTTP Error: {e.response.status_code}")
        return None

9. Load Balancing и масштабирование

# В production много серверов за load balancer:
#
# Клиент → Load Balancer (nginx/HAProxy)
#                ↓
#         ┌──────┼──────┐
#         ↓      ↓      ↓
#       Server1 Server2 Server3
#
# Load Balancer распределяет запросы:
# - Round Robin (по очереди)
# - Least Connections (к серверу с меньше соединений)
# - IP Hash (по IP клиента)
# - Weighted (с учётом мощности сервера)

10. Безопасность

# HTTPS/TLS для шифрования
# - Все данные шифруются
# - Проверяется сертификат сервера
# - Защита от Man-in-the-Middle атак

import ssl

context = ssl.create_default_context()
context.check_hostname = True
context.verify_mode = ssl.CERT_REQUIRED

# Authentication и Authorization
# - Token (JWT, Bearer)
# - Basic Auth (username:password)
# - OAuth2, OpenID Connect

headers = {
    "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Итоговая схема

КЛИЕНТ                              СЕРВЕР
  ↓
  └─ DNS Lookup (IP)
     └─ TCP Handshake (3-way)
        └─ TLS Handshake (HTTPS)
           └─ HTTP Request (POST /users)
              └─────────────────────────→ Receive
                                         Parse
                                         Validate
                                         Process
                                         Database
              ←───────────────────────── HTTP Response
        └─ Parse Response
           └─ Render Data

Это фундамент для понимания всех типов интеграций: REST API, WebSockets, gRPC и микросервисной архитектуры.