Skip to main content

A Django application that provides UDP-based service discovery functionality

Project description

django-udp-discovery

A Django application that provides UDP-based service discovery functionality, allowing clients on a local network to automatically discover and connect to Django servers without hardcoded IP addresses.

Features

  • Automatic Service Discovery: Django servers automatically respond to UDP discovery requests
  • Zero Configuration: Works out of the box with sensible defaults
  • Thread-Safe: Background daemon thread that doesn't block Django
  • Configurable: All settings can be customized via Django settings
  • Production Ready: Comprehensive error handling and graceful shutdown
  • Well Tested: Full test coverage with isolated test cases

Platform Support

⚠️ Important: The current version of django-udp-discovery is not supported on macOS. This package is designed for Windows and Linux environments. If you need macOS support, please check for future releases or contribute to the project.

Quick Start

Installation

pip install django-udp-discovery

Basic Usage

  1. Add to your Django INSTALLED_APPS:
INSTALLED_APPS = [
    # ... your other apps
    'django_udp_discovery',
]
  1. The UDP discovery service starts automatically when Django loads!

  2. Clients can now discover your server by sending a UDP message to port 9999 (default).

Manual Control

Using Management Command

The start_discovery management command provides enhanced control over the UDP discovery service:

# Start the service (runs indefinitely)
python manage.py start_discovery

# Start the service for a specific duration (in seconds)
python manage.py start_discovery --duration 60   # Run for 60 seconds
python manage.py start_discovery --duration 120   # Run for 120 seconds (2 minutes)
python manage.py start_discovery --duration 3600  # Run for 3600 seconds (1 hour)

Features:

  • Automatically stops any existing service before starting
  • Handles port conflicts by freeing the port and restarting
  • Optional duration-based auto-stop with automatic cleanup
  • Graceful shutdown on Ctrl+C interruption

Using Python API

from django_udp_discovery import start_udp_service, stop_udp_service, is_running

# Check if service is running
if is_running():
    print("Discovery service is active")

# Manually start/stop if needed
start_udp_service()
stop_udp_service()

Configuration

Customize the discovery service in your Django settings.py:

# UDP Discovery Settings
DISCOVERY_PORT = 9999              # UDP port for discovery (default: 9999)
DISCOVERY_MESSAGE = "DISCOVER_SERVER"  # Discovery message (default: "DISCOVER_SERVER")
RESPONSE_PREFIX = "SERVER_IP:"     # Response prefix (default: "SERVER_IP:")
DISCOVERY_TIMEOUT = 0.5            # Client timeout in seconds (default: 0.5)
DISCOVERY_BUFFER_SIZE = 1024       # UDP buffer size in bytes (default: 1024)
ENABLE_LOGGING = True              # Enable logging (default: True)

Debugging and Console Logging

To enable debugging and see detailed information in the console about the UDP discovery service, you must add the following logging configuration to your Django project's settings.py:

# Logging configuration
# https://docs.djangoproject.com/en/5.2/topics/logging/
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '{levelname} {asctime} {module} {message}',
            'style': '{',
        },
        'simple': {
            'format': '{levelname} {message}',
            'style': '{',
        },
    },
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
            'formatter': 'simple',
        },
    },
    'loggers': {
        'django_udp_discovery': {
            'handlers': ['console'],
            'level': 'DEBUG' if DEBUG else 'INFO',
            'propagate': False,
        },
    },
}

This configuration will output debug information to the console, including:

  • Service startup and shutdown events
  • Discovery request messages received
  • Server responses sent
  • Error messages and port conflicts
  • Service status changes

Note: The log level automatically adjusts based on your DEBUG setting - DEBUG level when DEBUG=True, INFO level when DEBUG=False.

How It Works

  1. Server Side: When Django starts, a background thread begins listening on the configured UDP port
  2. Client Discovery: Clients send a UDP broadcast with the discovery message
  3. Server Response: The server validates the message and responds with its IP address
  4. Client Connection: Clients receive the IP and can connect to the server

Protocol

The discovery protocol is simple:

  • Discovery Message: Client sends DISCOVER_SERVER (configurable) as a UDP message
  • Response Format: Server responds with SERVER_IP:<ip_address> (configurable prefix)
  • Port: Default 9999 (configurable)

Requirements

  • Python 3.7+
  • Django 3.4+ (or Django 2.2+ with app config)

Testing

Run the test suite:

python manage.py test django_udp_discovery

Test Results

Latest test results are available in the test_results directory. All 21 tests pass successfully, covering:

  • Configuration management (4 tests)
  • UDP listener service lifecycle (6 tests)
  • Management command functionality (11 tests)

See test_results/README.md for detailed test results and coverage information.

Documentation

Comprehensive documentation is available in the following locations:

Project Structure

django-udp-discovery/
├── src/                         # Source code directory
│   └── django_udp_discovery/    # Python package (installable)
│       ├── __init__.py          # Package initialization
│       ├── apps.py              # Django app configuration
│       ├── conf.py              # Configuration management
│       ├── listener.py          # UDP listener implementation
│       ├── utility.py           # Common utility functions
│       ├── README.md            # Package documentation
│       └── management/          # Django management commands
│           └── commands/
│               └── start_discovery.py  # Manual service control command
├── tests/                       # Test suite (not in package)
│   └── tests.py                 # Comprehensive test suite
├── test_project/                # Test Django project (for prototyping)
├── test_results/                # Test results and reports (gitignored)
│   ├── README.md                # Test results summary
│   └── test_output.txt          # Full test output
├── pyproject.toml               # Package configuration (PEP 621)
├── MANIFEST.in                  # Package manifest
├── LICENSE                      # MIT License
└── README.md                    # This file

Production Usage Examples

Example 1: Basic Server Setup

A complete example of setting up a Django server with UDP discovery:

settings.py:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django_udp_discovery',  # Add this
]

# UDP Discovery Configuration
DISCOVERY_PORT = 9999
DISCOVERY_MESSAGE = "DISCOVER_SERVER"
RESPONSE_PREFIX = "SERVER_IP:"
ENABLE_LOGGING = True

# Logging configuration for debugging
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '{levelname} {asctime} {module} {message}',
            'style': '{',
        },
        'simple': {
            'format': '{levelname} {message}',
            'style': '{',
        },
    },
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
            'formatter': 'simple',
        },
    },
    'loggers': {
        'django_udp_discovery': {
            'handlers': ['console'],
            'level': 'DEBUG' if DEBUG else 'INFO',
            'propagate': False,
        },
    },
}

The service will start automatically when you run your Django server:

python manage.py runserver

Example 2: Production Server with Custom Configuration

For production environments, you may want to customize the discovery settings:

settings.py (production):

# Production UDP Discovery Settings
DISCOVERY_PORT = 7777  # Custom port
DISCOVERY_MESSAGE = "FIND_MY_SERVER"  # Custom discovery message
RESPONSE_PREFIX = "my_server_ip:"  # Custom response prefix
ENABLE_LOGGING = True

# Production logging (INFO level, not DEBUG)
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '{levelname} {asctime} {module} {message}',
            'style': '{',
        },
    },
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
            'formatter': 'verbose',
        },
    },
    'loggers': {
        'django_udp_discovery': {
            'handlers': ['console'],
            'level': 'INFO',  # Use INFO for production
            'propagate': False,
        },
    },
}

Example 4: Using the Management Command in Production

For production deployments, you can use the management command to control the service:

# Start for a specific duration (useful for scheduled tasks)
python manage.py start_discovery --duration 3600  # 1 hour

# Use with process managers like systemd or supervisor
# systemd service example:
# [Service]
# ExecStart=/path/to/venv/bin/python /path/to/manage.py start_discovery

Example 5: Programmatic Control

Control the service programmatically in your Django views or management commands:

from django_udp_discovery import start_udp_service, stop_udp_service, is_running
from django.http import JsonResponse

def service_status(request):
    """API endpoint to check discovery service status"""
    return JsonResponse({
        'running': is_running(),
        'status': 'active' if is_running() else 'inactive'
    })

def start_service(request):
    """API endpoint to start the discovery service"""
    if start_udp_service():
        return JsonResponse({'status': 'started'})
    return JsonResponse({'status': 'failed'}, status=500)

def stop_service(request):
    """API endpoint to stop the discovery service"""
    if stop_udp_service():
        return JsonResponse({'status': 'stopped'})
    return JsonResponse({'status': 'failed'}, status=500)

License

See LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Support

For issues, questions, or contributions, please use the project's issue tracker.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_udp_discovery-1.0.0.tar.gz (30.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_udp_discovery-1.0.0-py3-none-any.whl (35.1 kB view details)

Uploaded Python 3

File details

Details for the file django_udp_discovery-1.0.0.tar.gz.

File metadata

  • Download URL: django_udp_discovery-1.0.0.tar.gz
  • Upload date:
  • Size: 30.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for django_udp_discovery-1.0.0.tar.gz
Algorithm Hash digest
SHA256 f8b8941e72e7701e4f62240437ff2e750d5da3f60000a3bd78645b6658c399ad
MD5 e0448b94be8eb35b1f2ca3e83bd24de1
BLAKE2b-256 4bd8145f956bb3ff0f5c900793ab074181110d73e66255a5ca3629d8687786c9

See more details on using hashes here.

File details

Details for the file django_udp_discovery-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for django_udp_discovery-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a65f763dc72c3756f17a01c6012b7166c9c86e9b8285e29f97d703fafa665e7b
MD5 420e40e7f281fad9ff28d8c5b0875dbf
BLAKE2b-256 7acf430469138bd1e7af7eb46addd06305b349982aadf27fc364957ce2f8929c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page