Skip to content

IoT Communication Protocols — MQTT, CoAP & HTTP Guide

DodaTech Updated 2026-06-21 7 min read

In this tutorial, you'll learn about IoT Communication Protocols. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

IoT communication protocols define how devices exchange data across networks, with MQTT, CoAP, and HTTP each optimized for different constraints — bandwidth, power, latency, and reliability — in the Internet of Things ecosystem.

What You'll Learn

You'll understand the differences between MQTT, CoAP, and HTTP/2 for IoT, when to choose each protocol, implement pub/sub with MQTT, request-response with CoAP, and benchmark protocol performance.

Why IoT Protocols Matter

IoT devices range from battery-powered sensors (lasting years on a coin cell) to mains-powered gateways. Choosing the wrong protocol wastes power, bandwidth, or development time. At DodaTech, our IoT Security scanner uses CoAP for sensor data (2-byte overhead) and MQTT for alerts (reliable delivery) — each protocol matched to its task.

Real-World Use Case

A smart building with 2,000 sensors initially uses HTTP polling. Each sensor sends 1KB every minute = 2MB/min from the gateway. Switching to MQTT with QoS 0 reduces overhead to 4 bytes per message, cutting bandwidth by 99.6% and extending sensor battery life from 3 to 18 months.

Protocol Comparison

Feature MQTT CoAP HTTP/2
Transport TCP UDP TCP
Header Size 2 bytes 4 bytes 200+ bytes
Model Pub/Sub Request/Response Request/Response
QoS 0, 1, 2 Confirmable, Non-confirmable None
Security TLS DTLS TLS
Best For Reliable messaging Constrained devices Rich APIs

MQTT Implementation

MQTT uses a broker to decouple publishers and subscribers:

import paho.mqtt.client as mqtt
import json
import time

# Sensor data publisher
def on_connect(client, userdata, flags, rc):
    print(f"Connected with result code {rc}")

client = mqtt.Client()
client.on_connect = on_connect
client.connect("broker.emqx.io", 1883, 60)

temperature = 22.5
humidity = 55

while True:
    payload = json.dumps({
        "device_id": "sensor-01",
        "temperature": temperature,
        "humidity": humidity,
        "timestamp": time.time()
    })
    
    # Publish with QoS 1 (at least once)
    result = client.publish("building/floor1/temperature", 
                           payload, qos=1)
    
    if result.rc == mqtt.MQTT_ERR_SUCCESS:
        print(f"Published: {payload}")
    else:
        print(f"Publish failed: {result.rc}")
    
    temperature += 0.1
    time.sleep(10)

Expected output: Every 10 seconds, the script publishes JSON sensor data to the MQTT broker. QoS 1 guarantees delivery at least once.

MQTT Subscriber

import paho.mqtt.client as mqtt

def on_message(client, userdata, msg):
    print(f"Topic: {msg.topic}")
    print(f"Payload: {msg.payload.decode()}")
    
    # Parse and process
    import json
    data = json.loads(msg.payload.decode())
    if data["temperature"] > 30:
        print("ALERT: High temperature detected!")

subscriber = mqtt.Client()
subscriber.on_message = on_message
subscriber.connect("broker.emqx.io", 1883, 60)
subscriber.subscribe("building/floor1/#", qos=1)

print("Listening for sensor data...")
subscriber.loop_forever()

Expected output: The subscriber receives all messages matching building/floor1/# and prints both the raw payload and a temperature alert if threshold is exceeded.

CoAP Implementation

CoAP uses UDP with retransmission for constrained devices:

from aiocoap import *
import asyncio
import json

# CoAP Server (runs on sensor)
async def coap_server():
    class SensorResource(Resource):
        async def render_get(self, request):
            payload = json.dumps({
                "temperature": 22.5,
                "humidity": 55,
                "battery": 85
            }).encode()
            
            return Message(
                payload=payload,
                code=CONTENT,
                content_format=ContentFormat.APPLICATION_JSON
            )
    
    root = Site()
    root.add_resource(['sensor', 'data'], SensorResource())
    
    await Context.create_server_context(root, bind=('0.0.0.0', 5683))
    await asyncio.get_running_loop().create_future()

# CoAP Client
async def coap_client():
    protocol = await Context.create_client_context()
    
    request = Message(
        code=GET,
        uri='coap://localhost:5683/sensor/data'
    )
    
    response = await protocol.request(request).response
    data = json.loads(response.payload.decode())
    print(f"CoAP Response: {data}")
    print(f"Response code: {response.code}")
    print(f"RTT: {response.opt.max_age}")

if __name__ == "__main__":
    # Run server in one terminal, client in another
    asyncio.run(coap_server())
    # asyncio.run(coap_client())

Expected output: CoAP client retrieves sensor data with a 4-byte header — ideal for 802.15.4 and LoRaWAN networks.

HTTP/2 for IoT Gateways

import httpx
import asyncio

async def http_iot_gateway():
    async with httpx.AsyncClient(http2=True) as client:
        # Batch sensor readings via POST
        response = await client.post(
            "https://api.iot-platform.com/v1/sensors/batch",
            json={
                "gateway_id": "gw-bldg-01",
                "readings": [
                    {"sensor": "temp-01", "value": 22.5},
                    {"sensor": "humidity-01", "value": 55},
                    {"sensor": "pressure-01", "value": 1013}
                ]
            },
            timeout=30
        )
        print(f"HTTP/2 Status: {response.status_code}")
        print(f"Response: {response.json()}")

# HTTP/2 multiplexing — 10 requests in parallel
async def batch_requests():
    async with httpx.AsyncClient(http2=True) as client:
        tasks = []
        for i in range(10):
            tasks.append(
                client.get(f"https://api.iot-platform.com/v1/sensors/{i}")
            )
        responses = await asyncio.gather(*tasks)
        for r in responses:
            print(f"Sensor {r.url}: {r.status_code}")

Expected output: HTTP/2 multiplexes 10 requests over a single TCP connection, reducing latency by eliminating connection overhead per request.

Mermaid Diagram: Protocol Selection Flow

flowchart TD
    A[IoT Device] --> B{Power Source?}
    B -->|Battery| C{Data Frequency?}
    B -->|Mains| D{Message Pattern?}
    C -->|Low| E[CoAP]
    C -->|High| F[MQTT QoS 0]
    D -->|Pub/Sub| F
    D -->|Request/Response| G[REST API]
    G --> H{Constrained?}
    H -->|Yes| E
    H -->|No| I[HTTP/2]
    style A fill:#e6f3ff
    style E fill:#d4edda
    style F fill:#fff3cd
    style I fill:#cce5ff

Protocol Benchmark

Metric MQTT CoAP HTTP/2
100 msgs overhead 200 bytes 400 bytes 20KB
Battery (AA, daily use) 18 months 36 months 6 months
Max throughput 10K msg/s 2K req/s 50K req/s
NAT-friendly Yes (persistent conn) No (UDP) Yes
TLS overhead ~5KB handshake ~3KB (DTLS) ~6KB

Common Protocol Errors

1. MQTT Topic Wildcard Mismatch

Problem: sensor/+/temperature vs sensor/# — wrong wildcard. Fix: + replaces one level, # matches all remaining levels.

2. CoAP Non-Confirmable Lost

Problem: Non-confirmable message lost without retry. Fix: Use Confirmable (CON) for important data, Non-confirmable (NON) for telemetry.

3. HTTP Polling Overhead

Problem: Device polls every 5 seconds — 17K messages/month wasted. Fix: Switch to MQTT push or HTTP/2 Server-Sent Events.

4. MQTT Retained Messages Confusion

Problem: New subscriber gets stale retained message. Fix: Set retain flag only for state (current temperature), not events (alerts).

5. DTLS Handshake Failures

Problem: CoAP over DTLS fails on memory-constrained MCUs. Fix: Use pre-shared keys (PSK) instead of certificates — 1/10th the memory.

6. Port Blocking

Problem: Corporate firewall blocks port 1883 (MQTT) or 5683 (CoAP). Fix: Use MQTT over WebSockets (port 443) or CoAP over HTTP proxy.

Practice Questions

  1. Why does MQTT use a broker? Decouples publishers from subscribers — devices don't need to know each other's addresses.

  2. What does QoS 2 guarantee? Exactly-once delivery using a four-part handshake — highest reliability, highest overhead.

  3. When would you choose CoAP over MQTT? When using UDP-only networks (LoRaWAN, 802.15.4) or when device memory is under 100KB.

  4. What is MQTT's last will and testament? A message the broker publishes if the client disconnects unexpectedly — used for device status monitoring.

  5. How does HTTP/2 improve IoT compared to HTTP/1.1? Multiplexing, header compression (HPACK), server push, and binary framing — all reduce latency.

Challenge

Build an IoT protocol gateway that accepts MQTT messages from field devices and translates them to HTTP/2 REST calls for a cloud platform. Handle QoS mapping, retry logic, and connection pooling. Benchmark throughput with 1,000 simulated devices.

Real-World Task

You deploy 500 soil moisture sensors on a farm. Each sensor reports every 30 minutes. Battery life estimate with HTTP polling: 4 months. With CoAP NON: 24 months. Implement CoAP on the sensor firmware (ESP32) and benchmark actual power consumption with a current meter.

Mini Project: Multi-Protocol Bridge

import paho.mqtt.client as mqtt
import httpx
import json
import asyncio

class MQTTtoHTTPBridge:
    def __init__(self, mqtt_broker, http_endpoint):
        self.http_endpoint = http_endpoint
        self.client = mqtt.Client()
        self.client.on_message = self.on_mqtt_message
        self.client.connect(mqtt_broker)
        
    def on_mqtt_message(self, client, userdata, msg):
        data = json.loads(msg.payload.decode())
        asyncio.create_task(
            self.forward_to_cloud(data)
        )
    
    async def forward_to_cloud(self, data):
        async with httpx.AsyncClient() as http:
            response = await http.post(
                self.http_endpoint,
                json=data,
                timeout=5
            )
            print(f"Forwarded: {response.status_code}")
    
    def start(self):
        self.client.subscribe("sensors/#")
        self.client.loop_forever()

This bridge translates MQTT sensor readings to cloud HTTP API calls.

  • MQTT — MQTT protocol deep dive
  • CoAP — CoAP for constrained devices
  • IoT Cloud Platforms — Cloud ingestion endpoints
  • Next: IoT Edge Computing — Processing Data at the Edge Guide
  • Previous: IoT Overview — Internet of Things fundamentals
Can I use MQTT without a broker?

No — MQTT requires a broker. For peer-to-peer scenarios, consider CoAP over UDP or MQTT-SN (Sensor Networks) with a gateway.

What is MQTT-SN?

MQTT for Sensor Networks — optimized for Zigbee and other low-power radios. Uses UDP, smaller packet headers, and supports gateway-based broker access.

How do I secure IoT communications?

Use TLS for MQTT, DTLS for CoAP, HTTPS for HTTP. For constrained devices, use pre-shared keys (PSK) instead of certificates. Always encrypt payloads end-to-end for sensitive data.

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro