diff --git a/examples/protocols/sockets/tcp_transport_client/CMakeLists.txt b/examples/protocols/sockets/tcp_transport_client/CMakeLists.txt new file mode 100644 index 0000000000..888ca62b16 --- /dev/null +++ b/examples/protocols/sockets/tcp_transport_client/CMakeLists.txt @@ -0,0 +1,10 @@ +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(tcp_transport_client) diff --git a/examples/protocols/sockets/tcp_transport_client/README.md b/examples/protocols/sockets/tcp_transport_client/README.md new file mode 100644 index 0000000000..6f3649b29d --- /dev/null +++ b/examples/protocols/sockets/tcp_transport_client/README.md @@ -0,0 +1,59 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | + + +# TCP TRANSPORT Client example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +The application creates a TCP transport connection and tries to connect to the server with predefined IP address and port number. When a connection is successfully established, the application sends message and waits for the answer. After the server's reply, application prints received reply as ASCII text, waits for 2 seconds and sends another message. + +## How to use example + +In order to create TCP server that communicates with TCP TRANSPORT Client example, choose one of the following options. + +There are many host-side tools which can be used to interact with the UDP/TCP server/client. +One command line tool is [netcat](http://netcat.sourceforge.net) which can send and receive many kinds of packets. +Note: please replace `192.168.0.167 3333` with desired IPV4/IPV6 address (displayed in monitor console) and port number in the following command. + +In addition to those tools, simple Python scripts can be found under sockets/scripts directory. Every script is designed to interact with one of the examples. + +### TCP server using netcat +``` +nc -l 192.168.0.167 3333 +``` + +## Hardware Required + +This example can be run on any commonly available ESP32 development board. + +## Configure the project + +``` +idf.py menuconfig +``` + +Set following parameters under Example Configuration Options: + +* Set `IPV4 Address` that represents remote host the example will connect to. + +* Set `Port` number that represents remote port the example will connect to. + +Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. + +## Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +idf.py -p PORT flash monitor +``` + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + + +## Troubleshooting + +Start server first, to receive data sent from the client (application). diff --git a/examples/protocols/sockets/tcp_transport_client/main/CMakeLists.txt b/examples/protocols/sockets/tcp_transport_client/main/CMakeLists.txt new file mode 100644 index 0000000000..1365c27b1e --- /dev/null +++ b/examples/protocols/sockets/tcp_transport_client/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "tcp_transport_client.c" + ) diff --git a/examples/protocols/sockets/tcp_transport_client/main/Kconfig.projbuild b/examples/protocols/sockets/tcp_transport_client/main/Kconfig.projbuild new file mode 100644 index 0000000000..3bee48e876 --- /dev/null +++ b/examples/protocols/sockets/tcp_transport_client/main/Kconfig.projbuild @@ -0,0 +1,16 @@ +menu "Example Configuration" + + config EXAMPLE_IPV4_ADDR + string "IPV4 Address" + default "192.168.0.165" + help + The example will connect to this IPV4 address. + + config EXAMPLE_PORT + int "Port" + range 0 65535 + default 3333 + help + The remote port to which the client example will connect to. + +endmenu diff --git a/examples/protocols/sockets/tcp_transport_client/main/tcp_transport_client.c b/examples/protocols/sockets/tcp_transport_client/main/tcp_transport_client.c new file mode 100644 index 0000000000..c6b10e0b13 --- /dev/null +++ b/examples/protocols/sockets/tcp_transport_client/main/tcp_transport_client.c @@ -0,0 +1,85 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "esp_netif.h" +#include "protocol_examples_common.h" +#include "esp_transport.h" +#include "esp_transport_tcp.h" + + +#define HOST_IP_ADDR CONFIG_EXAMPLE_IPV4_ADDR + +#define PORT CONFIG_EXAMPLE_PORT + +static const char *TAG = "tcp_transport_client"; +static const char *payload = "Message from ESP32"; + +static void tcp_transport_client_task(void *pvParameters) +{ + char rx_buffer[128]; + char host_ip[] = HOST_IP_ADDR; + esp_transport_handle_t tcp = esp_transport_tcp_init(); + while (1) { + if (tcp == NULL) { + ESP_LOGE(TAG, "Error occurred during esp_transport_tcp_init()"); + break; + } + int err = esp_transport_connect(tcp, HOST_IP_ADDR, PORT, -1); + if (err != 0) { + ESP_LOGE(TAG, "Client unable to connect: errno %d", errno); + break; + } + ESP_LOGI(TAG, "Successfully connected"); + + while (1) { + int bytes_written = esp_transport_write(tcp, payload, strlen(payload), 0); + if (bytes_written < 0) { + ESP_LOGE(TAG, "Error occurred during sending: esp_transport_write() returned %d, errno %d", bytes_written, errno); + break; + } + int len = esp_transport_read(tcp, rx_buffer, sizeof(rx_buffer) - 1, 0); + // Error occurred during receiving + if (len < 0) { + ESP_LOGE(TAG, "recv failed: esp_transport_read() returned %d, errno %d", len, errno); + break; + } + // Data received + rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string + ESP_LOGI(TAG, "Received %d bytes from %s:", len, host_ip); + ESP_LOGI(TAG, "%s", rx_buffer); + + vTaskDelay(2000 / portTICK_PERIOD_MS); + } + + ESP_LOGE(TAG, "Shutting down TCP and restarting..."); + esp_transport_close(tcp); + } + esp_transport_destroy(tcp); + vTaskDelete(NULL); +} + +void app_main(void) +{ + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); + + xTaskCreate(tcp_transport_client_task, "tcp_transport_client", 4096, NULL, 5, NULL); +}