How Do Devices Talk? Unraveling Network Protocols, RPC, and CAN Basics
This article explains the fundamentals of device communication, from simple LAN setups using hubs and switches to internet protocols like HTTP, then guides the design of custom communication protocols, illustrates JSON‑RPC over sockets, and explores CAN bus specifics, offering practical code examples and architectural diagrams.
Background
In a restaurant kitchen there are many devices with different functions, types, and communication mechanisms. Basic front‑end and back‑end communication uses defined interfaces over HTTP, but when two devices need to talk they must be physically or wirelessly connected.
Common communication methods include serial (USB, CAN), Bluetooth, and TCP. Although the media differ, the underlying principles are similar.
A Simple Network
Imagine a computer that wants to chat with another computer. They connect via a network port and a cable, then communicate.
When a third computer joins, another port is added and all three are linked.
As more participants join, the number of ports grows, leading to the idea of a middleman that forwards messages.
This middleman is a hub . It receives a message from one device and forwards it to all others.
However, a hub notifies every device for each message, which is inefficient and insecure. A smarter device, a switch , can send a message directly to the intended recipient by maintaining a MAC‑to‑port mapping.
When the number of devices grows, multiple switches are used, and eventually a router is introduced to connect different LANs.
A router assigns IP addresses via DHCP or manual configuration and keeps a mapping of IP to MAC addresses, often using ARP.
How the Internet Works
HTTP is the fundamental protocol of the Internet, defining the communication format between client and server, including request and response structures.
What is a Communication Protocol?
Syntax (data format and encoding) – e.g., UTF‑8, GBK
Semantics (control information and error handling) – e.g., CRC
Speed (throughput and ordering) – e.g., MTU
Just like two people need to agree on a language and sentence meaning before talking.
Application Layer Protocol HTTP
HTTP is an application‑level protocol built on top of TCP/IP.
Getting Information from the Network
HTTP provides URIs, methods, and headers for clients to express intent to servers.
Client request
Server response
Design a Simple Communication Protocol
What details must a communication protocol contain?
Core of Protocol Design
High parsing efficiency
Extensibility
Protocol Design Details
Data frame integrity check
Serialization / deserialization
Versioning and compatibility
Security, encryption, attack resistance
Data compression
Message Integrity Judgment
Fixed‑size delimiter (e.g., 8‑byte blocks padded with zeros)
Special symbol delimiter (e.g., \r\n)
Header + body structure
Timeout‑based completeness (not recommended)
Example
Request packet (partial) fields:
{
"id": "123",
"jsonrpc": "2.0",
"method": "ability.getInfo",
"params": null
}Response packet:
{
"id": "123",
"code": 0,
"result": {}
}The response must contain the same id to match the request.
Thus, using the lightweight, stateless JSON‑RPC protocol over sockets satisfies the requirements.
How Client Initiates a Request and Receives a Response
Simplified flow:
Talk about RPC Design and Implementation
RPC (Remote Procedure Call)
RPC requires defining methods that can be invoked remotely, allowing parameter passing, return values, and exception handling, making remote calls feel like local calls.
Challenges include network loss, timeouts, idempotency, and serialization overhead.
Client request example
const userInfo = rpc.getUserInfo(params);Server registration example
server.registerMethod('getUserInfo', (Parameters params) => {
return {"name": "bill"};
});RPC Basic Model
Components:
gateway_client – client stub
gateway_server – server stub
gateway_data_util – encoding/decoding
socket_base – transport layer
The overall architecture implements a custom protocol based on JSON‑RPC over sockets.
Async to Sync
Transforming asynchronous socket messages into synchronous calls simplifies business logic.
socket.on('message', (data) => {
if (data.method == 'userInfo') {
// handle userInfo
}
print('Message from server: $data');
});Using async/await: var userInfo = await getUserInfo(); Each request is treated as a future; timeouts and errors are propagated accordingly.
Core Implementation
Construct pending request map
Future send({
String? method,
int cmd = GatewayCmd.dataPost,
Map<String, dynamic>? parameters,
}) async {
Completer completer = Completer();
completer.future.timeout(const Duration(seconds: timeoutSeconds),
onTimeout: () {
completer.completeError(RpcException.timeout());
});
int id = GatewayDataUtil().seqIncrement();
_send(deviceId, cmd, method, parameters, id);
_pendingRequests[id] = _Request(method, completer);
return completer.future;
}Send request
class _Request {
final String? method;
final Completer completer;
_Request(this.method, this.completer);
}Handle response
void onReceiveSocketData(dynamic response) {
int? id;
Map? jsonMap = response;
if (jsonMap != null) {
id = int.tryParse(jsonMap["id"]);
}
if (id == null) return;
if (_pendingRequests.containsKey(id)) {
_Request request = _pendingRequests.remove(id)!;
if (jsonMap != null) {
request.completer.complete(jsonMap);
} else {
request.completer.complete();
}
} else {
logger.i("Response id $id not found in pending requests");
}
}Key Points
Ensure each request has a unique ID (JSON‑RPC id).
Protocol layer must distinguish between server‑initiated messages and client responses.
Example: CAN Protocol
CAN is a serial communication protocol for LANs, originally designed for automotive electronics.
All devices connect to a CAN bus; each device receives all frames but filters out those not addressed to it. Arbitration ensures the frame with the lowest ID wins bus access.
Standard frames use 11‑bit identifiers; extended frames use 29‑bit identifiers. Data payload is up to 8 bytes; larger payloads require segmentation.
Mapping Keys and Distinguishing Requests
Use destination address + command + packet sequence as the map key, but duplicate commands may cause collisions.
Determine whether a message is a client request or a server‑initiated response by checking the pending request map.
var request = _pendingRequests.remove(key);
if (request == null) {
// server‑initiated message
} else {
// client request response
}Cancel duplicate pending requests:
if (_pendingRequests[key] != null) {
_Request? request = _pendingRequests.remove(key);
request?.completer.completeError({"error": "Task cancelled"});
logger.i("Cancelled command $cmd on target $targetAddress");
}Architecture Diagram
The diagram shows the current device‑to‑device communication architecture, including middleware, mock, cache, and retry logic handled at the application layer.
Goodme Frontend Team
Regularly sharing the team's insights and expertise in the frontend field
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
