Skip to content

Conversation

@zhhyu7
Copy link
Contributor

@zhhyu7 zhhyu7 commented Dec 25, 2025

Summary

CLOSE-WAIT - represents waiting for a connection termination request
from the local user.
TCP A TCP B

  1. ESTABLISHED ESTABLISHED
  2. (Close)
    FIN-WAIT-1 --> <SEQ=100><ACK=300><CTL=FIN,ACK> --> CLOSE-WAIT
  3. FIN-WAIT-2 <-- <SEQ=300><ACK=101><CTL=ACK> <-- CLOSE-WAIT
  4.                                                   (Close)
    
    TIME-WAIT <-- <SEQ=300><ACK=101><CTL=FIN,ACK> <-- LAST-ACK
  5. TIME-WAIT --> <SEQ=101><ACK=301><CTL=ACK> --> CLOSED
  6. (2 MSL)
    CLOSED

in the current state, we can continue to send data until the user calls shutdown or close, then directly enter the TCP_LAST_ACK state

Impact

TCP supports half-open state

Testing

sim:matter with test code
Linux TCP test code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <signal.h>
#include <stdbool.h>

#define SERVER_IP "0.0.0.0"
#define PORT 7777
#define BUFFER_SIZE 1024

bool running = true;
void signal_handler(int signum) {
    printf("Signal %d received\n", signum);
    running = false;
}

int main() {
    int server_fd, client_fd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t addr_len = sizeof(client_addr);
    char buffer[BUFFER_SIZE] = "hello";

    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) {
        perror("invalid address");
        close(server_fd);
        exit(EXIT_FAILURE);
    }

   if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr))) {
        perror("bind failed");
        close(server_fd);
        exit(EXIT_FAILURE);
    }

    if (listen(server_fd, 5) < 0) {
        perror("listen failed");
        close(server_fd);
        exit(EXIT_FAILURE);
    }
    signal(SIGTERM, signal_handler);
    signal(SIGKILL, signal_handler);
    signal(SIGABRT, signal_handler);
    signal(SIGSEGV, signal_handler);
    signal(SIGILL, signal_handler);
    signal(SIGFPE, signal_handler);
    signal(SIGBUS, signal_handler);
    signal(SIGPIPE, signal_handler);
    printf("Server listening on %s:%d\n", SERVER_IP, PORT);

    while (running) {
        if ((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &addr_len)) < 0) {
            perror("accept failed");
            sleep(10);
        }
        printf("accept success\n");

        sleep(1);
        close(client_fd);
    }

    close(server_fd);
    return 0;
}

NuttX TCP test code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <signal.h>
#include <poll.h>

#define SERVER_IP "10.0.1.1"
#define PORT 7777
#define BUFFER_SIZE 1024

void signal_handler(int signum) {
    printf("Signal %d received\n", signum);
}

int main(int argc, char *argv[]) {
    int sockfd;
    struct sockaddr_in server_addr;
    char buffer[BUFFER_SIZE];

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) {
        perror("invalid address");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr))) {
        perror("connection failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    signal(SIGTERM, signal_handler);
    signal(SIGKILL, signal_handler);
    signal(SIGABRT, signal_handler);
    signal(SIGSEGV, signal_handler);
    signal(SIGILL, signal_handler);
    signal(SIGFPE, signal_handler);
    signal(SIGBUS, signal_handler);
    signal(SIGPIPE, signal_handler);

    printf("Connected to server %s:%d\n", SERVER_IP, PORT);

    sleep(2);
    close(sockfd);
    return 0;
}

test log, interaction process of packet capture:

tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on nuttx0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
15:29:42.198036 IP 10.0.1.2.15151 > zhhyu-HP-Pro-Tower-480-G9-PCI-Desktop-PC.7777: Flags [S], seq 1282192172, win 16384, options [mss 1460], length 0
15:29:42.198109 IP zhhyu-HP-Pro-Tower-480-G9-PCI-Desktop-PC.7777 > 10.0.1.2.15151: Flags [S.], seq 66148653, ack 1282192173, win 64240, options [mss 1460], length 0
15:29:42.198172 IP 10.0.1.2.15151 > zhhyu-HP-Pro-Tower-480-G9-PCI-Desktop-PC.7777: Flags [.], ack 1, win 16384, length 0
15:29:43.198447 IP zhhyu-HP-Pro-Tower-480-G9-PCI-Desktop-PC.7777 > 10.0.1.2.15151: Flags [F.], seq 1, ack 1, win 64240, length 0
15:29:43.402420 IP zhhyu-HP-Pro-Tower-480-G9-PCI-Desktop-PC.7777 > 10.0.1.2.15151: Flags [F.], seq 1, ack 1, win 64240, length 0
15:29:43.408069 IP 10.0.1.2.15151 > zhhyu-HP-Pro-Tower-480-G9-PCI-Desktop-PC.7777: Flags [.], ack 2, win 16384, length 0
15:29:44.207867 IP 10.0.1.2.15151 > zhhyu-HP-Pro-Tower-480-G9-PCI-Desktop-PC.7777: Flags [F.], seq 1, ack 2, win 16384, length 0
15:29:44.207923 IP zhhyu-HP-Pro-Tower-480-G9-PCI-Desktop-PC.7777 > 10.0.1.2.15151: Flags [.], ack 2, win 64240, length 0

@github-actions github-actions bot added Area: Networking Effects networking subsystem Size: S The size of the change in this PR is small labels Dec 25, 2025
Copy link
Contributor

@acassis acassis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zhhyu7 nice work, please update the Documentation to reflect this support:
https://nuttx.apache.org/docs/latest/components/net/index.html

@zhhyu7
Copy link
Contributor Author

zhhyu7 commented Dec 26, 2025

reflect

Hi @acassis , Currently, there is no existing documentation explaining the overall TCP process. Given the extensive content of TCP, it is not easy to compile a detailed documentation. Would it be better to submit a separate PR to supplement the explanation of TCP?

@github-actions github-actions bot added the Size: M The size of the change in this PR is medium label Dec 26, 2025
@acassis
Copy link
Contributor

acassis commented Dec 26, 2025

reflect

Hi @acassis , Currently, there is no existing documentation explaining the overall TCP process. Given the extensive content of TCP, it is not easy to compile a detailed documentation. Would it be better to submit a separate PR to supplement the explanation of TCP?

@zhhyu7 you are completely right, the "best" Documentation we have is maybe this one that Greg wrote: https://nuttx.apache.org/docs/latest/components/net/delay_act_and_tcp_perf.html

But I suggest you to just use it as starting point and write a small and basic Documentation, then over the time we will evolve it. It is better than no documentation at all.

@github-actions github-actions bot added the Area: Documentation Improvements or additions to documentation label Dec 27, 2025
@zhhyu7
Copy link
Contributor Author

zhhyu7 commented Dec 27, 2025

reflect

Hi @acassis , Currently, there is no existing documentation explaining the overall TCP process. Given the extensive content of TCP, it is not easy to compile a detailed documentation. Would it be better to submit a separate PR to supplement the explanation of TCP?

@zhhyu7 you are completely right, the "best" Documentation we have is maybe this one that Greg wrote: https://nuttx.apache.org/docs/latest/components/net/delay_act_and_tcp_perf.html

But I suggest you to just use it as starting point and write a small and basic Documentation, then over the time we will evolve it. It is better than no documentation at all.

@acassis I've added a basic description document on how NuttX implements TCP state transitions. Please review it again. Thank you a lot.

@zhhyu7 zhhyu7 requested a review from acassis December 27, 2025 02:09
@xiaoxiang781216
Copy link
Contributor

@zhhyu7 please fix:

Warning, treated as error:
/home/runner/work/nuttx/nuttx/Documentation/components/net/tcp_state_machine.rst:document isn't included in any toctree
make: *** [Makefile:48: html] Error 2

CLOSE-WAIT - represents waiting for a connection termination request
             from the local user.
      TCP A                                                TCP B

  1.  ESTABLISHED                                          ESTABLISHED
  2.  (Close)
      FIN-WAIT-1  --> <SEQ=100><ACK=300><CTL=FIN,ACK>  --> CLOSE-WAIT
  3.  FIN-WAIT-2  <-- <SEQ=300><ACK=101><CTL=ACK>      <-- CLOSE-WAIT
  4.                                                       (Close)
      TIME-WAIT   <-- <SEQ=300><ACK=101><CTL=FIN,ACK>  <-- LAST-ACK
  5.  TIME-WAIT   --> <SEQ=101><ACK=301><CTL=ACK>      --> CLOSED
  6.  (2 MSL)
      CLOSED

in the current state, we can continue to send data until the user
calls shutdown or close, then directly enter the TCP_LAST_ACK state

Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
Copy link
Contributor

@acassis acassis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zhhyu7 amazing!!! Kudos

@zhhyu7
Copy link
Contributor Author

zhhyu7 commented Dec 27, 2025

@zhhyu7 please fix:

Warning, treated as error:
/home/runner/work/nuttx/nuttx/Documentation/components/net/tcp_state_machine.rst:document isn't included in any toctree
make: *** [Makefile:48: html] Error 2

Done.

@xiaoxiang781216 xiaoxiang781216 merged commit 746d689 into apache:master Dec 27, 2025
41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: Documentation Improvements or additions to documentation Area: Networking Effects networking subsystem Size: M The size of the change in this PR is medium Size: S The size of the change in this PR is small

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants