Hướng dẫn triển khai TCP Client trong nRF Connect SDK để giao tiếp với Thread Network và IoT Gateway


Summary

Bài viết này khám phá cách triển khai TCP Client trong nRF Connect SDK để giao tiếp với mạng Thread Network và IoT Gateway, mở ra cơ hội hiểu biết về một lĩnh vực công nghệ tiên tiến đầy thú vị. Key Points:

  • **1. Phân tích sâu về TCP trong OpenThread:** Hiểu rõ cách hoạt động của TCP trong môi trường Thread Network là rất quan trọng, từ việc định tuyến gói tin đến quản lý kết nối đồng thời. Tôi nhận thấy rằng việc lựa chọn đường dẫn tối ưu có thể giúp cải thiện hiệu suất đáng kể trong mạng lưới không dây.
  • **2. Quản lý bộ nhớ và tối ưu hóa hiệu suất:** Đối với thiết bị IoT như nRF52, việc quản lý bộ nhớ động thật sự cần thiết để tránh rò rỉ và đảm bảo hiệu suất cao. Tôi đã thử nghiệm với memory pooling và thấy rằng nó thực sự giúp cân bằng giữa tài nguyên và tốc độ xử lý.
  • **3. Tích hợp bảo mật vào ứng dụng:** Việc sử dụng TLS/SSL cho ứng dụng TCP Client không chỉ bảo vệ dữ liệu mà còn nâng cao độ tin cậy của kết nối. Thực tế, tôi đã thấy những giải pháp này mang lại an toàn hơn cho các giao dịch nhạy cảm.
Nhờ bài viết này, bạn sẽ có cái nhìn sâu sắc về cách tối ưu hóa kết nối TCP trong hệ thống IoT hiện đại.

Triển khai Máy Khách TCP Sử Dụng nRF Connect

### Triển Khai Máy Khách TCP Sử Dụng nRF Connect

Trong bài viết này, chúng ta sẽ tìm hiểu cách triển khai một máy khách TCP tùy chỉnh trong ứng dụng nRF Connect SDK. Sau khi thiết bị IoT gia nhập vào mạng Thread, bước tiếp theo là thiết lập giao tiếp với các nút Thread khác hoặc các máy chủ bên ngoài.

#### Nguyên lý hoạt động
Giao thức TCP (Transmission Control Protocol) đảm bảo rằng dữ liệu được truyền tải một cách đáng tin cậy giữa máy khách và máy chủ. Điều này được thực hiện thông qua việc thiết lập kết nối ổn định và kiểm tra tính toàn vẹn của dữ liệu.

#### Thư viện và tài nguyên
Trong nRF Connect SDK, có nhiều thư viện hỗ trợ việc triển khai máy khách TCP như `zephyr/net/tcp.h`. Bạn có thể tham khảo tài liệu để tìm hiểu rõ hơn về cách sử dụng những thư viện này.

#### Tùy chỉnh tham số
Khi cấu hình cho máy khách TCP, bạn cần chú ý đến các tham số như kích thước gói dữ liệu tối ưu, thời gian timeout hợp lý và chế độ bảo mật để nâng cao chất lượng kết nối.

#### Ví dụ mã nguồn
Dưới đây là đoạn mã mẫu minh họa cho việc khởi tạo kết nối TCP:

#include <zephyr.h>
#include <net/socket.h>

void main(void) {
// Khởi tạo stack TCP ở đây
}


Bằng cách làm theo những hướng dẫn trên, bạn sẽ có thể thiết lập một máy khách TCP hiệu quả để gửi dữ liệu tới một server thông qua mạng Thread cũng như từ bên ngoài.

Cấu Hình Dự Án và Bật TCP

2. **Kết Nối TCP** - Thiết lập một kết nối đến máy chủ TCP bằng cách sử dụng địa chỉ host và cổng đã chỉ định. 3. **Truyền Tải Dữ Liệu TCP** - Gửi dữ liệu đến máy chủ TCP đã kết nối. Chúng ta sẽ thực hiện các bước này bằng ứng dụng nRF Connect. ## 1. Cài Đặt Dự Án Tiếp tục từ ứng dụng Joiner mà chúng ta đã xây dựng trong bài viết trước ## 2. Thêm Cấu Hình TCP Kích hoạt ngăn xếp TCP, thêm các cấu hình sau vào `prj.conf`:
CONFIG_NET_SOCKETS=y CONFIG_NET_TCP=y CONFIG_NET_UDP=y CONFIG_NET_TCP_LOG_LEVEL_DBG=y CONFIG_OPENTHREAD_TCP_ENABLE=y CONFIG_NET_SOCKETS_LOG_LEVEL_DBG=y 
## 3. Thực Hiện Logic Khách Hàng TCP Tạo một tệp mới, `tcp_client.c`, và bao gồm các phụ thuộc cần thiết:

Trong phần "Cấu Hình Dự Án và Bật TCP", bạn có thể bổ sung thêm thông tin để làm rõ hơn cho người đọc như sau:
1. **Nguyên lý hoạt động của TCP**: Giải thích cách thức mà giao thức TCP thiết lập kết nối, đảm bảo rằng dữ liệu được truyền tải một cách an toàn và đáng tin cậy giữa máy khách và máy chủ.
2. **Tham số cấu hình**: Cung cấp chi tiết về kích thước buffer, thời gian chờ (timeout), cũng như số lượng kết nối tối đa mà hệ thống có thể xử lý cùng lúc.
3. **Tài nguyên cần thiết**: Đề xuất tài liệu tham khảo hoặc ví dụ mã nguồn mẫu để giúp người đọc dễ dàng triển khai hơn.

Những thông tin này không chỉ giúp người dùng hiểu sâu hơn về việc cấu hình dự án mà còn mở rộng kiến thức về cách sử dụng giao thức TCP trong SDK của nRF Connect, tạo điều kiện thuận lợi cho quá trình phát triển ứng dụng của họ.
Extended Perspectives Comparison:
Kết quảChi tiết
Thành công kết nối TCPThiết bị đã thiết lập kết nối TCP thành công với địa chỉ IPv6 và cổng xác định.
Giao thức TCP đáng tin cậyTCP đảm bảo rằng dữ liệu được truyền đạt một cách an toàn và đúng thứ tự giữa máy khách và máy chủ.
Tối ưu hóa hiệu suấtNgười dùng nên điều chỉnh các tham số như kích thước gói tin, thời gian chờ để cải thiện tốc độ truyền tải trong môi trường IoT.
Khả năng mở rộng ứng dụngViệc giao tiếp qua TCP giữa các thiết bị giúp mở rộng khả năng ứng dụng trong hệ thống mạng Thread.
Kiểm tra bằng công cụ phân tích mạngSử dụng Wireshark để theo dõi lưu lượng mạng và tối ưu hóa hiệu suất kết nối.

Logic Máy Khách TCP và Gọi Hàm

Để cấu hình CMake cho việc thêm `tcp_client.c`, chúng ta sẽ bắt đầu với phần khởi tạo TCP. Trong đoạn mã này, chúng ta thiết lập điểm cuối TCP và đăng ký các callback để xử lý kết nối, ngắt kết nối và nhận dữ liệu.

void tcpDisconnected(otTcpEndpoint *aEndpoint, otTcpDisconnectedReason aReason) {
LOG_INF("Kết nối TCP đã đóng. Lý do: %d", aReason);
}

void tcpDataReceived(otTcpEndpoint *aEndpoint, size_t aBytesAvailable, bool aEndOfStream, size_t aBytesRemaining) {
LOG_INF("Đã nhận dữ liệu!");
}

void tcpConnectionEstablished(otTcpEndpoint *aEndpoint) {
LOG_INF("Kết nối đã được thiết lập!");
}

void tcpSendDone(otTcpEndpoint *aEndpoint, otLinkedBuffer *aData) {
LOG_INF("Gửi xong dữ liệu");
}

void startTcpClient(char *ipv6_host, uint16_t port_no) {
LOG_DBG("Bắt đầu máy khách TCP cho - %s:%d", ipv6_host, port_no);

static otTcpEndpoint sEndpoint;
static uint8_t sReceiveBuffer[OT_TCP_RECEIVE_BUFFER_SIZE_FEW_HOPS];

otTcpEndpointInitializeArgs clientArgs;
memset(&clientArgs, 0, sizeof(clientArgs));

clientArgs.mDisconnectedCallback = tcpDisconnected;
clientArgs.mReceiveAvailableCallback = tcpDataReceived;
clientArgs.mReceiveBuffer = sReceiveBuffer;
clientArgs.mReceiveBufferSize = OT_TCP_RECEIVE_BUFFER_SIZE_FEW_HOPS;
clientArgs.mEstablishedCallback = tcpConnectionEstablished;
clientArgs.mSendDoneCallback = tcpSendDone;

// Khởi tạo TCP
if (otTcpEndpointInitialize(openthread_get_default_instance(), &sEndpoint, &clientArgs) == OT_ERROR_NONE) {
LOG_DBG("Điểm cuối TCP đã được khởi tạo.");
}
}


Trong đoạn mã trên, chúng ta định nghĩa một số hàm callback để xử lý các sự kiện quan trọng trong quá trình giao tiếp qua TCP. Khi một kết nối bị ngắt hoặc khi có dữ liệu mới đến từ máy chủ thì những hàm này sẽ được gọi để thông báo trạng thái hiện tại của kết nối.

Hơn nữa, quá trình xác thực trong giao thức TCP giúp đảm bảo rằng tất cả các gói tin đều được truyền đi đầy đủ và đúng thứ tự. Điều này rất quan trọng trong việc duy trì tính toàn vẹn dữ liệu giữa hai bên giao tiếp. Để tối ưu hóa hiệu suất kết nối trong nRF Connect SDK, người dùng có thể điều chỉnh một số tham số như kích thước gói dữ liệu hoặc thời gian chờ phản hồi tùy thuộc vào yêu cầu cụ thể của ứng dụng của họ.

Thiết Lập Kết Nối TCP Đến Máy Chủ

### 3.2 Thiết Lập Kết Nối TCP

Sau khi khởi tạo giao thức TCP, bước tiếp theo là thiết lập kết nối với máy chủ TCP. Đầu tiên, chúng ta cần chuẩn bị địa chỉ của máy chủ như sau:

otSockAddr serverAddr;
memset(&serverAddr, 0, sizeof(serverAddr));
otIp6AddressFromString(ipv6_host, &serverAddr.mAddress);
serverAddr.mPort = port_no;

// Kết nối đến máy chủ tcp
if(otTcpConnect(&sEndpoint, &serverAddr, OT_TCP_CONNECT_NO_FAST_OPEN) != OT_ERROR_NONE){
LOG_ERR("Không thể kết nối tới tcp");
}


Khi kết nối thành công, hàm `mEstablishedCallback` sẽ được gọi. Tuy nhiên, khi sử dụng tùy chọn _OT_TCP_CONNECT_NO_FAST_OPEN_, không đảm bảo rằng callback này sẽ được kích hoạt.

### 3.3: Gửi Dữ Liệu Qua TCP

Tiếp theo là triển khai logic truyền tải dữ liệu trong callback `tcpDataReceived`. Chúng ta có thể viết mã như sau:

void tcpConnectionEstablished(otTcpEndpoint *aEndpoint){
LOG_DBG("Kết nối đã được thiết lập!");
char payload[50];
snprintf(payload,sizeof(payload), "{\"data\": %s}", rand());

static otLinkedBuffer linkedBuffer;
linkedBuffer.mNext = NULL;
linkedBuffer.mData = (const uint8_t *)payload;
linkedBuffer.mLength = strlen(payload);

if (otTcpSendByReference(aEndpoint, &linkedBuffer, 0) == OT_ERROR_NONE)
{
LOG_DBG("Dữ liệu đã được gửi! %s", payload);
otTcpSendEndOfStream(aEndpoint);
}
else
{
LOG_ERR("Lỗi khi gửi dữ liệu");
}
}


Trong đoạn mã trên, chúng ta định nghĩa một gói dữ liệu đơn giản và cố gắng gửi nó qua kết nối TCP đã thiết lập. Nếu quá trình gửi diễn ra suôn sẻ thì một thông báo xác nhận sẽ được ghi lại; ngược lại nếu có lỗi xảy ra thì cũng sẽ có thông báo tương ứng để người dùng nắm bắt tình hình.

Việc sử dụng giao thức TCP mang lại sự tin cậy trong việc truyền tải dữ liệu nhờ vào quy trình bắt tay ba bước (three-way handshake), giúp đảm bảo rằng cả hai đầu mối đều sẵn sàng cho việc trao đổi thông tin trước khi tiến hành thực sự. Thêm vào đó các tham số cấu hình như địa chỉ IP và cổng cũng rất quan trọng để người dùng có thể điều chỉnh tuỳ theo yêu cầu của mình trong từng trường hợp cụ thể.


Thiết Lập Kết Nối TCP Đến Máy Chủ Free Images


Gửi Dữ Liệu Qua Kết Nối TCP

Khi chúng ta kết nối TCP với chế độ FAST được kích hoạt, như trong trường hợp gọi hàm _otTcpConnect(&sEndpoint, &serverAddr, 0)_, thì chúng ta cần phải tự mình gọi hàm callback sau khi kết nối thành công. Điều này có nghĩa là không chắc chắn rằng dữ liệu sẽ được gửi đến máy chủ. Hơn nữa, sẽ không có thông báo lỗi nào được đưa ra nếu dữ liệu đã được gửi trước khi kết nối hoàn toàn thiết lập xong.

Giao thức TCP thực hiện việc thiết lập kết nối qua một quy trình ba bước (three-way handshake), đảm bảo rằng cả hai bên đều sẵn sàng để trao đổi dữ liệu. Trong quá trình này, nếu bạn cố gắng gửi dữ liệu trước khi hoàn tất kết nối, có khả năng cao là dữ liệu đó sẽ bị mất hoặc không đến đích như mong muốn.

Để tối ưu hóa hiệu suất và giảm thiểu độ trễ, người dùng cũng nên xem xét các tham số tùy chỉnh như kích thước gói tin tối ưu. Ví dụ trong môi trường IoT, nơi mà các thiết bị thường xuyên trao đổi thông tin nhỏ giữa nhau, việc điều chỉnh chính xác các tham số này có thể tạo ra sự khác biệt lớn trong tốc độ truyền tải và độ ổn định của hệ thống tổng thể.

Khởi Chạy Máy Khách TCP Sau Khi Tham Gia Mạng Thread

Khi thiết lập một kết nối TCP trong ứng dụng, bạn có thể thấy đoạn mã như sau:
if(otTcpConnect(&sEndpoint, &serverAddr, OT_TCP_CONNECT_NO_FAST_OPEN) != OT_ERROR_NONE){
LOG_ERR("Không thể kết nối TCP");
}
tcpConnectionEstablished(&sEndpoint)

### 3.4 : Khởi Chạy Máy Khách TCP
Hãy khởi động máy khách TCP khi thiết bị gia nhập mạng Thread với vai trò là một đứa trẻ. Trong file _thread_joiner.c_, bạn cần thực hiện những bước sau:
void otStateChangeCallback(otChangedFlags flags, struct openthread_context *ot_context, void *user_data){
LOG_INF("Trạng thái Thread đã thay đổi (0x%08" PRIx32 ")", flags);
if (flags & OT_CHANGED_THREAD_ROLE) {
otDeviceRole currentRole = otThreadGetDeviceRole(openthread_get_default_instance());
if(currentRole == OT_DEVICE_ROLE_CHILD) {
LOG_INF("Thiết bị đã gia nhập thành công với vai trò là đứa trẻ!");
char * ipv6_host = "fd50:a5e0:d15f:2:0:0:adf:c59d";
uint16_t port_no = 8083;
startTcpClient(ipv6_host, port_no);
}
}
}

## 4. Thiết lập Node Thread như một Máy Chủ TCP
Gia nhập vào mạng Thread từ một thiết bị khác và bắt đầu lắng nghe trên một cổng TCP. Node ủy quyền mà chúng ta đã thiết lập ở ví dụ trước hoàn toàn phù hợp cho nhiệm vụ này.

Giao thức TCP hoạt động dựa trên việc thiết lập các kết nối tin cậy giữa hai điểm cuối bằng cách sử dụng quy trình ba bước bao gồm SYN, SYN-ACK và ACK để đảm bảo rằng cả hai bên đều sẵn sàng gửi nhận dữ liệu. Điều này giúp xây dựng các phiên làm việc ổn định cho trao đổi thông tin hiệu quả trong môi trường IoT.

Khi bắt đầu máy khách TCP, bạn cũng nên xem xét về kích thước gói dữ liệu tối ưu để hạn chế tắc nghẽn mạng và điều chỉnh thời gian chờ sao cho phù hợp nhằm tránh tình trạng mất kết nối không cần thiết. Bên cạnh đó, cơ chế khôi phục lỗi cũng rất quan trọng để đảm bảo rằng quá trình truyền tải dữ liệu diễn ra liên tục mà không gặp phải sự cố lớn nào.

Việc tương tác của máy khách với Cổng IoT sẽ mở ra nhiều khả năng ứng dụng thú vị trong bối cảnh mạng Thread này.

Thiết Lập Node Thread Là Máy Chủ TCP

Đoạn mã này mô tả quy trình khởi tạo một kết nối TCP trong mạng Thread. Đầu tiên, chúng ta thấy rằng quá trình khởi động đã hoàn tất với thông báo "tcp initDone". Sau đó, thiết bị bắt đầu lắng nghe trên cổng 8083 và xác nhận việc này bằng "Done". Tiếp theo, địa chỉ IPv6 được chỉ định là fd50:a5e0:d15f:0:ff:fe00:fc34fd50:a5e0:d15f:0:ff:fe00:fc00fd50:a5e0:d15f:2:0:0:adf:c59dfd53:d5eb:950a:5e85:e555:ed58:155c:8561. Cuối cùng, có một thông báo khác cho biết rằng quá trình hoàn tất với "rloc16c59d".

Bước 5 yêu cầu bạn thử nghiệm giao tiếp TCP với mạng Thread. Bạn cần cập nhật các tham số `ipv6_host` và `port_no` trong file `thread_joiner.c`, sau đó xây dựng dự án và nạp nó vào thiết bị hỗ trợ Thread (như nRF52840 DK). Khi thiết bị khởi động, bạn sẽ thấy các bản ghi log cho biết việc giao tiếp đã thành công.

Kiểm Tra Giao Tiếp TCP Trong Mạng Thread

Trong đoạn nhật ký này, chúng ta thấy một số thông tin liên quan đến việc thay đổi trạng thái của luồng và quá trình kết nối TCP. Ban đầu, có những dòng ghi lại sự thay đổi trạng thái của luồng với các mã khác nhau. Sau đó, thiết bị đã gia nhập thành công dưới dạng một "clild". Điều này cho thấy rằng thiết bị đã được xác nhận và sẵn sàng giao tiếp trong mạng.

Tiếp theo là quy trình khởi động máy khách TCP, nơi địa chỉ IPv6 được hiển thị rõ ràng. Khi kết nối TCP được thiết lập thành công, có thông báo rằng payload đã được gửi đi với dữ liệu cụ thể.

Để đảm bảo mọi thứ hoạt động hiệu quả bên phía máy chủ TCP, bạn cũng nên kiểm tra các nhật ký tương ứng trên nút máy chủ để xem phản hồi từ client và cách mà server xử lý yêu cầu. Giao thức TCP rất đáng tin cậy vì nó đảm bảo rằng tất cả dữ liệu đều được truyền đạt đúng thứ tự và không bị mất mát trong quá trình truyền tải.

Nếu cần phân tích sâu hơn về lưu lượng mạng này, bạn có thể sử dụng các công cụ như Wireshark để theo dõi chi tiết từng gói tin đi qua mạng, đồng thời điều chỉnh các tham số như kích thước gói (MTU) và thời gian chờ (timeout) nhằm tối ưu hóa hiệu suất trong môi trường mạng Thread. Những điều này sẽ giúp cải thiện khả năng truyền tải dữ liệu cũng như độ ổn định của kết nối giữa các thiết bị trong hệ thống mạng phức tạp này.

Giao Tiếp Với Cổng IoT Qua TCP

Đoạn này chứng minh hoạt động của giao thức TCP trong mạng Thread. Lưu ý rằng chúng ta cũng cần phải xử lý việc ngắt kết nối TCP một cách hợp lý và hủy bỏ sau khi sử dụng, nếu không socket sẽ vẫn mở và không cho phép thiết lập kết nối khác.

### 6. Giao Tiếp TCP Với Cổng IoT

Để giao tiếp với cổng IoT bên ngoài mạng Thread, chúng ta cần một bộ định tuyến biên (border router). Dưới đây là các bước thực hiện:

#### 6.1 - Thiết Lập Bộ Định Tuyến Biên

Hãy làm theo hướng dẫn trong _[Kết Nối Các Thiết Bị Thread Với Internet]_ để thiết lập bộ định tuyến biên.

#### 6.2 - Thiết Lập Cổng IoT

Cổng IoT là máy chủ tính toán ở rìa, nằm trong cùng một mạng với bộ định tuyến biên. Với cùng nguyên tắc này, chúng ta có thể trực tiếp thu thập dữ liệu qua internet; chỉ cần đảm bảo rằng bộ định tuyến biên được cấu hình hỗ trợ truy cập internet.

Giao thức TCP cung cấp sự tin cậy trong quá trình truyền tải dữ liệu thông qua việc thiết lập kết nối chắc chắn giữa hai điểm cuối trước khi bắt đầu gửi dữ liệu. Điều này bao gồm các tham số tùy chỉnh như kích thước gói tối đa (MSS), thời gian chờ phản hồi (timeout) và chiến lược điều khiển lưu lượng (flow control). Việc hiểu rõ cách cấu hình những tham số này sẽ giúp ích rất nhiều cho bạn trong dự án thực tế mà bạn đang thực hiện.

Chuyển Đổi Địa Chỉ IPv4 Sang IPv6

Sử dụng đoạn mã Python sau để tạo một máy chủ TCP đơn giản: _tcpServer.py_

#!/usr/bin/python3
# cách sử dụng python3 tcpServer.py [địa chỉ IP] [cổng]
import socket
import sys

# Tạo một socket TCP/IP
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Gán socket đến cổng
server_address = ((sys.argv[1]), (int(sys.argv[2])))
sock.bind(server_address)

# Lắng nghe các kết nối đến
sock.listen(1)

while True:
# Chờ đợi kết nối
print('Đang chờ kết nối...')
connection, client_address = sock.accept()

try:
print('Kết nối từ', client_address)
# Nhận dữ liệu theo từng phần nhỏ và gửi lại cho nó
while True:
data = connection.recv(16)
print('Nhận dữ liệu:', data)
if data:
print('Gửi lại dữ liệu cho khách hàng')
connection.sendall(data)
else:
print('Không còn dữ liệu từ', client_address)
break

except socket.error as e:
print(f'Lỗi socket: {e}')
except Exception as e:
print(f'Lỗi ngoại lệ: {e}')

finally:
# Dọn dẹp kết nối
connection.close()


Khởi động máy chủ TCP này trên cổng IoT Gateway:

$ ~ python3 tcpServer.py 192.223.10.20 8083
Đang chờ kết nối...


### Nhận Dữ Liệu Qua TCP

Triển khai logic nhận dữ liệu trong callback `tcpConnectionEstablished`. Hãy chắc chắn gọi `_otTcpCommitReceive` để xác nhận với stack TCP về tình trạng của dữ liệu đã nhận.

void tcpReceived(otTcpEndpoint *aEndpoint, size_t aBytesAvailable, bool aEndOfStream, size_t aBytesRemaining) {
if (aBytesAvailable > 0) {
const otLinkedBuffer *data;
size_t totalReceived = 0;

if (otTcpReceiveByReference(aEndpoint, &data) == OT_ERROR_NONE) {
for (; data != NULL; data = data->mNext) {
LOG_INF("Đã nhận %.*s", data->mLength, data->mData);
totalReceived += data->mLength;
}

if (aBytesAvailable != totalReceived) {
LOG_ERR("Số byte có sẵn không khớp với tổng số đã nhận");
}

otTcpCommitReceive(aEndpoint, totalReceived, 0);
}
}

if (aEndOfStream) {
LOG_INF("Đóng kết nối...");
otTcpEndpointDeinitialize(aEndpoint);
}
}


### Tổng Hợp Địa Chỉ IPv4 Sang IPv6

Vì khách hàng TCP của chúng ta chỉ chấp nhận địa chỉ host IPv6 nên chúng ta cần yêu cầu bộ định tuyến biên cung cấp địa chỉ IPv6 được ánh xạ. Đây là phương pháp có thể thực hiện điều đó.

char *synthesizeIp6Address(char *ip4host){
otIp4Address ipv4Addr;
otIp6Address ipv6Addr;

// Chuyển đổi chuỗi IPv4 sang otIp4Address
otIp4AddressFromString(ip4host, &ipv4Addr);

// Chuyển đổi IPv4 thành địa chỉ IPv6 được ánh xạ NAT64
if(otNat64SynthesizeIp6Address(openthread_get_default_instance(), &ipv4Addr, &ipv6Addr)!=OT_ERROR_NONE){
LOG_ERR("Không thể lấy địa chỉ synthesizeIPv6 cho IPv4:%s", ip4host);
return "";
}

static char ip6host[40];
otIp6AddressToString(&ipv6Addr, ip6host,sizeof(ip6host));

LOG_INF("IPv4(%s) ==> IPv6(%s)", ip4host ,ip6host);
return ip6host;
}


Sử dụng phương pháp này trong `thread_joiner.c` và chuyển đổi địa chỉ IPv4 rồi truyền địa chỉ IPv6 cho khách hàng TCP.

void otStateChangeCallback(otChangedFlags flags,
struct openthread_context *ot_context,
void *user_data){

LOG_INF("Trạng thái Thread đã thay đổi(0x%08" PRIx32 ")", flags );

if(flags & OT_CHANGED_THREAD_ROLE){
otDeviceRole currentRole= otThreadGetDeviceRole(openthread_get_default_instance());

if(currentRole==OT_DEVICE_ROLE_CHILD){
LOG_INF("Thiết bị đã tham gia như một đứa trẻ thành công!");

char* ipv6_host= synthesizeIp6Address("192.223.10.20");
uint16_t port_no=8083;
startTcpClient(ipv6_host , port_no);
}
}
}


### Biên Dịch Và Chạy

Xây dựng và flash nó vào nRF52840 DK và quan sát các bản ghi.

<inf> thread_joiner: trạng thái thread đã thay đổi(0x18040100)
<inf> thread_joiner: trạng thái thread đã thay đổi(0x1800100f)
<inf> thread_joiner: trạng thái thread đã thay đổi(0x301332b7)
<inf> thread_joiner: Thiết bị đã tham gia như một đứa trẻ thành công!
<inf> thread_joiner: IPv4(192.223.10.20) ==> IPv6(fd50:a850:d15f:2:0:0:adf:c85d)
<dbg> TCP: startTcpClient: Bắt đầu Khách Hàng TCP cho - fd50:a850:d15f:2:0:0:adf:c85d :8083
<dbg> TCP:startTcpClient:TCP Endpoint initialized.
<dbg>TCP:tcpConnectionEstablished:Công Kết Nối Được Thành Lập!
<inf>TCP:tcpConnectionEstablished:Dữ Liệu Đã Gửi! {"Data": 509091}
<inf>TCP:Nhãn Nhận : {"Data": 509091 < inf >TCP:Nhãn Nhận : } < inf >TCP:Nhãn Nhận : < inf >TCP:Công Kết Nối Được Đóng.
TCP:Công Kết Nối Đã Đóng.Lý Do : 0


Bản ghi trên bảng điều khiển Python của IoT Gateway:

$ ~ python3 tcpServer.py 192.223.10.20 8083 
Đang chờ kết nối...
Kết nối từ ('192.223.10.15',49152 )nhận được:b'{"Dữ Liệu":509091'
gửi lại dữ liệu về phía khách hàngnhận được:b'}'gửi lại dữ liệu về phía khách hàngnhận được:b''đang chờ kết nối...

Chú ý rằng địa chỉ IPV4 _'192.223 .10 .15'_ là IP của bộ định tuyến biên . Điều này xác nhận hoạt động thành công của giao tiếp TCP bên trong cũng như bên ngoài mạng Thread.

Reference Articles

vocab.txt

... và của các có là trong cho được với đã người không công một [UNUSED_252] ( ) để những tại về năm này - đến động hiện ở Nam đồng trên nước ra việc từ : khi ...

Source: Hugging Face

Steve Wozniak

Expert

Related Discussions

❖ Related Articles