yahboom
HomeLearn
Solution
Blog
Online Store
About Us
EN/中文
ESP32 Core Board📖
1. ESP32 Introduction
  • 1. ESP32S3 Overview
  • 2. Environment Setup Introduction
  • 3. Dev Board Introduction
2. ESP-IDF Development Tutorial
1. Before Development
  • 1. Environment Setup (Windows)
  • 2. Environment Setup (Linux)
  • 3. Build and Flash
2. Basic Peripherals
  • 1. LED Control
  • 2. Button Detection
  • 3. Peripheral Interrupts
  • 4. ESP_TIMER
  • 5. GPTIMER
  • 6. Watchdog Timer
  • 7. DMA
  • 8. ADC
  • 9. PWM Breathing LED
  • 10. RGB LED Effects
3. Serial Communication and Storage System
  • 1. Serial UART Communication Experiment
  • 2. I2C_OLED Display Experiment
  • 3. SPI Bus Communication Experiment
  • 4. PSRAM External Memory Experiment
  • 5. Flash Read and Write Experiment
  • 6. USB Emulated Mass Storage Experiment
4. FreeRTOS operating system
  • 1.FreeRTOS Core Concepts Theory
  • 2.Task Creation and Management
  • 3.Queue
  • 4.Binary Semaphore
  • 5.Mutex
  • 6.Event Groups
  • 7.Software Timer
  • 8.Task Scheduler
  • 9.Low Power Mode
  • 10.Deadlock
  • 11.Priority Inversion
5. Network Protocols and Wireless Communication
  • 1. WIFI Network Basics
  • 2. WIFI STA Mode
  • 3. WIFI AP Mode
  • 4. UDP Client Experiment
  • 5. UDP Server Experiment
  • 6. TCP Client Experiment
  • 7. TCP Server Experiment
  • 8. Socket Programming Basics
  • 9. HTTP Client Experiment
  • 10. HTTP Server Experiment
  • 11. MQTT IoT Communication Protocol
  • 12. WIFI OTA Upgrade
  • 13. Bluetooth Fundamentals
  • 14. Bluetooth Slave Mode
  • 15. Bluetooth Master Mode
6. Audio Applications
  • 1.I2S Microphone Recording and U-Disk Playback
  • 2.I2S Audio Playback Experiment
  • 3.Repeater Experiment
7. Xiaozhi AI Voice
  • 1. Burn Xiaozhi Firmware
  • 2. Network and Configuration
  • 3. AI Agent Settings
  • 4. Program Analysis
  • 5. Free Chat
3. Arduino Development Course
1. Before Development
  • 1. Environment Setup
  • 2. Build and Flash
2. Basic Peripherals
  • 1. LED Control
  • 2. Button Detection
  • 3. Peripheral Interrupts
  • 4. ESP_TIMER
  • 5. GPTIMER
  • 6. Watchdog Timer
  • 7. ADC
  • 8. PWM Breathing LED
  • 9. RGB LED Effects
3. Serial Communication and Storage System
  • 1. Serial UART Communication
  • 2. I2C OLED Display
  • 3. SPI Bus Communication
  • 4. Flash Read and Write
  • 5. USB Emulated Mass Storage
4. Network Protocols and Wireless Communication
  • 1. WIFI Network Basics
  • 2. WIFI STA Mode
  • 3. WIFI AP Mode
  • 4. UDP Server Experiment
  • 5. UDP Client Experiment
  • 6. TCP Client Experiment
  • 7. TCP Server Experiment
  • 8. HTTP Client Experiment
  • 9. HTTP Server Experiment
  • 10. MQTT IoT Communication Protocol
  • 11. WIFI OTA Upgrade
  • 12. Bluetooth Fundamentals
  • 13. Bluetooth Slave Mode
  • 14. Bluetooth Master Mode
5. Audio Applications
  • 1.I2S Microphone Recording and U-Disk Playback
  • 2.I2S Audio Playback Experiment
  • 3.Repeater Experiment
4. MicroPython Development Course
1. Before Development
  • 1. Environment Setup
  • 2. Build and Flash
  • 3. Thonny IDE
2. Basic Peripherals
  • 1. LED Control
  • 2. Button Detection
  • 3. Peripheral Interrupts
  • 4. TIMER_IT
  • 5. Watchdog Timer
  • 6. ADC
  • 7. PWM Breathing LED
  • 8. RGB LED Effects
3. Serial Communication and Storage System
  • 1. Serial UART Communication Experiment
  • 2. I2C_OLED Display Experiment
  • 3. SPI Bus Communication Experiment
  • 4. Flash Read and Write Experiment
  • 5. Print Storage
4. Network Protocols and Wireless Communication
  • 1. WIFI Network Basics
  • 2. WIFI STA Mode
  • 3. WIFI AP Mode
  • 4. UDP Client Experiment
  • 5. UDP Server Experiment
  • 6. TCP Client Experiment
  • 7. TCP Server Experiment
  • 8. HTTP Client Experiment
  • 9. HTTP Server Experiment
  • 10. MQTT
  • 11. Bluetooth Fundamentals
  • 12. Bluetooth Slave Mode
  • 13. Bluetooth Master Mode
5. Audio Applications
  • 1. I2S Audio Playback Experiment
  • 2. Repeater Experiment
Download
  • Code
  • Hardware_Info
  • 3D_Model_File
  • Software_Tools
  • VMware
  • VM_File
Download ZIP

Welcome to ESP32 Core Board repository

7. TCP Server Experiment

TCP Server


TCP Server1. TCP Server Overview2. Core Concepts2.1 TCP Server Processing Flow2.2 Single Client vs Multi-Client3. Hardware Dependencies4. Project Architecture and Flow5. Source Code Details5.1 Configuration and Global Variables5.2 setup() — Start Server5.3 loop() — State Machine Processing6. Operation Flow6.1 Build and Flash6.2 Operation Steps6.3 Verification Methods7. Common Issues


1. TCP Server Overview

TCP (Transmission Control Protocol) is a connection-oriented, reliable, byte-stream transport layer protocol. It establishes connections through three-way handshake, ensuring data arrives in order and intact.

TCP is the foundation of IoT communication. Whether it's HTTP web requests, MQTT message publishing, OTA firmware upgrades, or database remote connections, all rely on TCP's reliable transmission underneath. In industrial automation, smart home, and remote monitoring scenarios, devices report sensor data and receive control commands, requiring "no data loss, no order disruption" transmission guarantees—this is TCP's core value. UDP is faster but unreliable; TCP has the overhead of three-way handshake, but is worth it for the end-to-end acknowledgment and retransmission mechanism, which is irreplaceable in most IoT scenarios.

This experiment uses the WiFiServer class to wrap lwIP's TCP listen socket, adopting a single-client serial model—each processing loop only serves one client, waiting for new connections after disconnection.

Typical Application Scenarios:

Application TypeExample
Web ServerHTTP Server listening on port 80
IoT GatewayReceiving TCP connections from multiple sensor nodes
Remote ControlTelnet command line, custom protocols

2. Core Concepts

2.1 TCP Server Processing Flow

From startup to shutdown, a TCP server goes through 6 stages, each corresponding to an Arduino API:

socket()               create socket
   ↓    WiFiServer server(8080) done automatically during construction
bind(port)             bind port
   ↓    server.begin() internally calls bind(8080)
listen()               start listening
   ↓    server.begin() internally calls listen(), waiting for client connection
accept()               accept connection
   ↓    server.available() is equivalent to accept(), non-blocking
   ↓    returns WiFiClient object when new connection, returns empty object when no new connection
read / write           send and receive data
   ↓    read and write through WiFiClient object returned by accept
close()                close connection
       client.stop() release socket, complete four-way handshake
MethodClassFunctionBlocking?
server.begin()WiFiServerBind port and start listening (bind + listen)No
server.available()WiFiServerAccept new client connection (accept)No
client.available()WiFiClientQuery readable bytes in receive bufferNo
client.read(buf, len)WiFiClientRead data from receive bufferNo
client.write(buf, len)WiFiClientSend data to this clientNo
client.connected()WiFiClientCheck if client is still onlineNo
client.stop()WiFiClientClose connection with this clientNo

2.2 Single Client vs Multi-Client

This experiment only maintains one WiFiClient, which is a single-client serial model—only serves one client at a time, and can only accept new connections after the current client disconnects.

​x
// Single Client: One Variable
WiFiClient client;
client = server.available();

// Multiple Clients: Array Polling
WiFiClient clients[5];
for (int i = 0; i < 5; i++) {
  if (clients[i] && clients[i].connected()) {
    // Independent reading and writing for each client
  }
}

Single client model is suitable for teaching demonstrations; actual projects should use arrays to support multiple concurrent clients.


3. Hardware Dependencies

Pure software experiment. Must first connect to router via WIFI-STA.


4. Project Architecture and Flow

xxxxxxxxxx
setup()
  ├─ connectWiFi()
  └─ server.begin()                    // bind + listen

loop()
  ├─ hasClient=0 → server.available() try accept → 0→1 print Connected
  ├─ hasClient=1 → while(client.available()) drain data → reply
  ├─ write() failed → 1→0 print disconnected → stop()
  └─ new connection → old client 1→0 print disconnected → new client 0→1

5. Source Code Details

Complete source code: Source code → Arduino → 3.Network Communication → TCP_Server → TCP_Server.ino

5.1 Configuration and Global Variables

SSID and password can be modified according to actual environment. hasClient tracks client count (0=none, 1=connected), used for state machine control and disconnect detection.

xxxxxxxxxx
#include <WiFi.h>
#include <lwip/sockets.h>    // select() / FIONREAD / fd() / select, FIONREAD, raw fd access

// ==================== Config ====================
const char* WIFI_SSID = "Yahboom2";        // WiFi SSID
const char* WIFI_PASS = "yahboom890729";   // WiFi password
#define TCP_PORT          8080             // TCP listen port

WiFiServer server(TCP_PORT);               // TCP server object
WiFiClient client;                         // current client object
int hasClient = 0;                         // client count 0=none 1=connected

char recv_buf[128];                        // receive buffer
char send_buf[128];                        // send buffer

5.2 setup() — Start Server

After serial initialization, switch to STA mode → connect WiFi → server.begin() completes bind + listen.

xxxxxxxxxx
void setup() {
  Serial.begin(115200);
  delay(1000);

  WiFi.mode(WIFI_STA);                     // station mode
  connectWiFi();                           // connect to WiFi
  server.begin();                          // bind + listen, start server

  Serial.println("==================================");
  Serial.println(" TCP Server Startup successful!");
  Serial.print(" Server IP: ");
  Serial.println(WiFi.localIP());          // print server IP
  Serial.print(" Port: ");
  Serial.println(TCP_PORT);               // print listen port
  Serial.println("==================================");
}

5.3 loop() — State Machine Processing

The main loop has three trigger paths to detect client disconnection: ① server.available() new connection replaces old client ② client.write() reply failure ③ select()+FIONREAD detects FIN half-close state. hasClient ensures 0→1 prints Connected, 1→0 prints disconnected.

xxxxxxxxxx
void loop() {
  // ====== WiFi watchdog: auto reconnect ======
  if (WiFi.status() != WL_CONNECTED) {
    connectWiFi();
  }

  // ====== Trigger 1: new connection → replace old client ======
  WiFiClient newClient = server.available(); // non-blocking accept
  if (newClient) {
    if (hasClient == 1) {                  // old client still present
      Serial.println("Client disconnected"); // 1→0: print disconnect
      client.stop();                       // release old socket
    }
    client    = newClient;                 // hold new connection
    hasClient = 1;                         // 0→1: mark client present
    Serial.println("Client Connected");
  }

  if (hasClient == 0) {                    // no client, wait next loop
    delay(100);
    return;
  }

  // ====== Trigger 2: exchange → write fail → disconnect ======
  while (client.available()) {             // drain internal buffer
    char buf[128];
    int len = client.read((uint8_t*)buf, sizeof(buf) - 1); // read data
    if (len > 0) {
      buf[len] = '\0';                     // null terminate
      Serial.printf("Received: %s\n", buf);

      char reply[160];
      sprintf(reply, "Server OK: %s", buf); // build reply
      if (client.write((const uint8_t*)reply, strlen(reply)) <= 0) {
        // send failed → disconnect
        Serial.println("Client disconnected"); // print disconnect
        client.stop();                     // release socket
        hasClient = 0;                     // count back to 0
        client = WiFiClient();            // reset to empty
        return;
      }
      Serial.printf("Reply: %s\n", reply);
    }
  }

  // ====== Trigger 3: FIN detection ======
  int fd = client.fd();                    // get raw socket fd
  if (fd < 0) {                            // invalid fd = disconnected
    Serial.println("Client disconnected");
    client.stop();
    hasClient = 0;
    client = WiFiClient();
    return;
  }

  fd_set readSet;
  FD_ZERO(&readSet);
  FD_SET(fd, &readSet);                    // watch fd for readability
  struct timeval tv = {0, 0};              // zero wait = poll only
  if (select(fd + 1, &readSet, NULL, NULL, &tv) > 0) {    // socket readable
    int pending = 0;
    lwip_ioctl(fd, FIONREAD, &pending);    // query pending bytes
    if (pending == 0) {                    // readable + 0 bytes = FIN
      Serial.println("Client disconnected"); // instant disconnect
      client.stop();
      hasClient = 0;
      client = WiFiClient();
      return;
    }
  }

  delay(10);                               // 10ms polling interval
}

Three disconnect trigger paths: ① New connection replacement ② write() send failure ③ select+FIONREAD detects FIN. hasClient count ensures clear state, 0→1 prints Connected, 1→0 prints disconnected.


6. Operation Flow

6.1 Build and Flash

Arduino flash process: See Arduino → 1. Before Development → 2. Build and Flash.

  1. Build and flash

  2. Use network debugging assistant or TCP client to connect to Server IP:8080

6.2 Operation Steps

Step 1: Flash program, record server IP

Build and flash to ESP32-S3 development board. Open serial monitor (baud rate 115200), wait for WiFi connection success, and note down the server IP address printed in serial:

x
Connecting to WiFi: Yahboom2 (Attempt 1)
...
WiFi Connected successfully!
Server IP: 192.168.11.181
==================================
 TCP Server Startup successful!
 Server IP: 192.168.11.181
 Port: 8080
==================================

Step 2: Open network debugging assistant as TCP client

Open network debugging assistant on PC网络调试助手图标, configure with the following parameters:

PC Client Settings

Bind Local Host Address

ParameterValue
Protocol TypeTCP Client
Remote HostESP32 server IP recorded in Step 1 (e.g., 192.168.11.229)
Remote Port8080

Step 3: Send data, observe echo

Enter Hello YAHBOOM in the send area of the network debugging assistant and click send. After ESP32 receives it, it automatically replies Server OK: Hello YAHBOOM, and the serial monitor prints:

Serial Monitor Output

Network debugging assistant prints:

Network Debugging Assistant Output

xxxxxxxxxx
Received: Hello YAHBOOM `,// serial monitor prints:
Reply: Server OK: Hello YAHBOOM `,// serial monitor prints:

Step 4: Test disconnect and reconnect

Click "Disconnect" in the network debugging assistant. Serial monitor prints Client disconnected. Click "Connect" again, ESP32 automatically accepts new client, prints Client Connected, and restores normal send/receive.

Disconnect

6.3 Verification Methods

OperationExpected Result
Client connects and sends dataReceives "Server OK: "
Client disconnectsPrints "Client disconnected"
New client connectsAuto accepts, prints "Client Connected"

7. Common Issues

PhenomenonCauseSolution
Client disconnects but doesn't print disconnectedWiFiClient::connected() is unreliable for normal FINUse hasClient count + write() return value detection + server.available() new connection replacement
Client connects but gets no replyServer busy or occupied by other clientCheck if single client model is blocking
server.available() returns emptyNo new connectionNormal—non-blocking design, just continue polling
Multiple clients but can only serve oneSingle client object limitationChange to WiFiClient clients[5] array model
TCP Client Experiment
HTTP Client Experiment

COMPANY

  • About us
  • Team Style
  • Blog

LEARNING & EXPLORATION

  • Tutorials
  • Edge AI hardware
  • Educational robots
  • Embedded intelligent hardware

WHERE TO BUY

  • Yahboom Online Store
  • Amazon
  • Alibaba
  • AliExpress
  • Mercado

TECHNOLOGY SUPPORT

  • Email: support@yahboom.com

BE A DISTRIBUTOR

  • Email: sales@yahboom.com
QR Code

Copyright © 2017-2026 Yahboom. All Rights Reserved.

EN/中文