How to establish TCP communication in the mode of direct connection of Ethernet cable

Hi.My test environment was to connect the MCU to the computer using a network cable directly,and phy is lan8720a.
The configuration of computer:
ip: 192.168.124.4
net mask: 255.255.255.0
gateway: 192.168.124.1
The configuration of mcu:
ip: 192.168.124.121
net mask: 255.255.255.0
gateway: 192.168.124.1

Computer acts as a tcp-server,use port 9000, and mcu acts as a tcp-client. I follow the routine to establish a TCP connection between the MCU and the computer, my code as follows:

void vTCPSend(void* param)
{
    Socket_t xSocket;
    BaseType_t xAlreadyTransmitted = 0, xBytesSent = 0;
    TaskHandle_t xRxTask = NULL;
    size_t xLenToSend;

    /* Set the IP address (192.168.0.200) and port (1500) of the remote socket
       to which this client socket will transmit. */
    struct freertos_sockaddr xRemoteAddress;
    memset( &xRemoteAddress, 0, sizeof(xRemoteAddress) );
    xRemoteAddress.sin_port = FreeRTOS_htons( 9000 );
    xRemoteAddress.sin_address.ulIP_IPv4 = FreeRTOS_inet_addr_quick( 192, 168, 124, 4 );
    xRemoteAddress.sin_family = FREERTOS_AF_INET4;
    
    struct freertos_sockaddr xLocalAddress;
    memset( &xLocalAddress, 0, sizeof(xLocalAddress) );
    xLocalAddress.sin_port = FreeRTOS_htons( 9999 );
    xLocalAddress.sin_address.ulIP_IPv4 = FreeRTOS_inet_addr_quick( 192, 168, 124, 121 );
    xLocalAddress.sin_family = FREERTOS_AF_INET4;
    
    static const TickType_t xReceiveTimeOut = pdMS_TO_TICKS( 20000 );
    static const TickType_t xSendTimeOut = pdMS_TO_TICKS( 20000 );
    
    while(1)
    {
            /* Create a socket. */
        xSocket = FreeRTOS_socket( FREERTOS_AF_INET,
                                   FREERTOS_SOCK_STREAM,/* FREERTOS_SOCK_STREAM for TCP. */
                                   FREERTOS_IPPROTO_TCP );
        configASSERT( xSocket != FREERTOS_INVALID_SOCKET );
        /* Set a time out so a missing reply does not cause the task to block indefinitely. */
        FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
		FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xSendTimeOut ) );
//        FreeRTOS_bind(xSocket, &xLocalAddress, sizeof(xLocalAddress));
        
        if( FreeRTOS_connect( xSocket, &xRemoteAddress, sizeof( xRemoteAddress ) ) == 0 )
		{
            const char buf[] = "Hello World";
            unsigned short xTotalLengthToSend = strlen(buf);
			/* Keep sending until the entire buffer has been sent. */
            while( xAlreadyTransmitted < xTotalLengthToSend )
            {
                /* How many bytes are left to send? */
                xLenToSend = xTotalLengthToSend - xAlreadyTransmitted;
                xBytesSent = FreeRTOS_send( /* The socket being sent to. */
                                            xSocket,
                                            /* The data being sent. */
                                            &( buf[ xAlreadyTransmitted ] ),
                                            /* The remaining length of data to send. */
                                            xLenToSend,
                                            /* ulFlags. */
                                            0 );

                if( xBytesSent >= 0 )
                {
                    /* Data was sent successfully. */
                    xAlreadyTransmitted += xBytesSent;
                }
                else
                {
                    /* Error - break out of the loop for graceful socket close. */
                    break;
                }
            }

            /* Initiate graceful shutdown. */
            FreeRTOS_shutdown( xSocket, FREERTOS_SHUT_RDWR );

            /* Wait for the socket to disconnect gracefully (indicated by FreeRTOS\_recv()
               returning a -pdFREERTOS_ERRNO_EINVAL error) before closing the socket. */
            while( FreeRTOS_recv( xSocket, (char*)buf, xTotalLengthToSend, 0 ) >= 0 )
            {
                /* Wait for shutdown to complete. If a receive block time is used then
                   this delay will not be necessary as FreeRTOS_recv() will place the RTOS task
                   into the Blocked state anyway. */
                vTaskDelay( pdTICKS_TO_MS( 250 ) );

                /* Note - real applications should implement a timeout here, not just
                   loop forever. */
            }
        }

        /* The socket has shut down and is safe to close. */
        FreeRTOS_closesocket( xSocket );

		/* Pause for a short while to ensure the network is not too congested. */
        #define echoLOOP_DELAY	( ( TickType_t ) 150 / portTICK_PERIOD_MS )
		vTaskDelay( echoLOOP_DELAY );
    }
}

but log as follows:

FreeRTOS_IPInit
FreeRTOS_AddEndPoint: MAC: 00-00 IPv4: c0a87c79ip
prvIPTask started
PHY ID 7C0F0
xPhyReset: phyBMCR_RESET [0] ready
+TCP: advertise: 01E1 config 3100
prvEthernetUpdateConfig: LS mask 00 Force 1
Autonego ready: 00000004: full duplex 100 mbit high status
Link Status is high
eNetworkUp
IP Address: 192.168.124.121
Subnet Mask: 255.255.255.0
Gateway Address: 192.168.124.1
DNS Server Address: 0.0.0.0
FreeRTOS_connect: 1025 to c0a87c04ip:9000
Socket 1025 -> [192.168.124.4]:9000 State eCLOSED->eCONNECT_SYN
ARP c0a87c04ip miss using c0a87c04ip
ARP for c0a87c04ip (using c0a87c04ip): rc=0 00-00-00-00-00-00
Connect[c0a87c04ip:9000]: next timeout 1: 2000 ms
pxEasyFit: ARP c0a87c79ip -> c0a87c01ip
Heap: current 216 lowest 216
Network buffers: 60 lowest 58
Heap: current 1768 lowest 128
ARP c0a87c04ip miss using c0a87c04ip
ARP for c0a87c04ip (using c0a87c04ip): rc=0 00-00-00-00-00-00
Connect[c0a87c04ip:9000]: next timeout 2: 2000 ms
ARP c0a87c04ip miss using c0a87c04ip
ARP for c0a87c04ip (using c0a87c04ip): rc=0 00-00-00-00-00-00
Connect[c0a87c04ip:9000]: next timeout 3: 2000 ms

I don’t understand what’s going on. Can you help me analyze it?

Hi @slhuan,
Could you help capture your network packets on the computer side by wireshark or some other similar tool? I’d like to know if the ARP request works correctly on the environment. Looks like the MCU can’t get the MAC address for that IP address.

Thank you.


Now I use a switch to connect my board to computer successfully. It should be a problem that I connect my board to computer with network cables connectting directly.
I’m a beginner in network protocols, now i 'm having a new problem that my code in mcu just send a tcp data once. I want to know how to send data all the time in FreeRTOS-Plus-TCP?
Here’s my code:

void test(void* param)
{
    Socket_t xSocket;
    BaseType_t xAlreadyTransmitted = 0, xBytesSent = 0;
    TaskHandle_t xRxTask = NULL;
    size_t xLenToSend;

    /* Set the IP address (192.168.0.200) and port (1500) of the remote socket
       to which this client socket will transmit. */
    struct freertos_sockaddr xRemoteAddress;
    memset( &xRemoteAddress, 0, sizeof(xRemoteAddress) );
    xRemoteAddress.sin_port = FreeRTOS_htons( 9000 );
    xRemoteAddress.sin_address.ulIP_IPv4 = FreeRTOS_inet_addr_quick( 192, 168, 50, 6 );
    xRemoteAddress.sin_family = FREERTOS_AF_INET4;
    
    struct freertos_sockaddr xLocalAddress;
    memset( &xLocalAddress, 0, sizeof(xLocalAddress) );
    xLocalAddress.sin_port = FreeRTOS_htons( 9999 );
    xLocalAddress.sin_address.ulIP_IPv4 = FreeRTOS_inet_addr_quick( 192, 168, 50, 121 );
    xLocalAddress.sin_family = FREERTOS_AF_INET4;
    
    static const TickType_t xReceiveTimeOut = pdMS_TO_TICKS( 20000 );
    static const TickType_t xSendTimeOut = pdMS_TO_TICKS( 20000 );
    
    while(1)
    {
        /* Create a socket. */
        xSocket = FreeRTOS_socket( FREERTOS_AF_INET,
                                   FREERTOS_SOCK_STREAM,/* FREERTOS_SOCK_STREAM for TCP. */
                                   FREERTOS_IPPROTO_TCP );
        configASSERT( xSocket != FREERTOS_INVALID_SOCKET );
        /* Set a time out so a missing reply does not cause the task to block indefinitely. */
        FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
        FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xSendTimeOut ) );
//        FreeRTOS_bind(xSocket, &xLocalAddress, sizeof(xLocalAddress));
        if(FreeRTOS_issocketconnected(xSocket) != pdTRUE)
        {
            FreeRTOS_connect( xSocket, &xRemoteAddress, sizeof( xRemoteAddress ));
        }
        else
        {
            const char buf[] = "Hello World";
            unsigned short xTotalLengthToSend = strlen(buf);
            xAlreadyTransmitted = 0;
            xLenToSend = 0;
            xBytesSent = 0;
			/* Keep sending until the entire buffer has been sent. */
            while( xAlreadyTransmitted < xTotalLengthToSend )
            {
                /* How many bytes are left to send? */
                xLenToSend = xTotalLengthToSend - xAlreadyTransmitted;
                xBytesSent = FreeRTOS_send( /* The socket being sent to. */
                                            xSocket,
                                            /* The data being sent. */
                                            &( buf[ xAlreadyTransmitted ] ),
                                            /* The remaining length of data to send. */
                                            xLenToSend,
                                            /* ulFlags. */
                                            0 );

                if( xBytesSent >= 0 )
                {
                    /* Data was sent successfully. */
                    xAlreadyTransmitted += xBytesSent;
                }
                else
                {
                    /* Error - break out of the loop for graceful socket close. */
                    break;
                }
            }

            /* Initiate graceful shutdown. */
            FreeRTOS_shutdown( xSocket, FREERTOS_SHUT_RDWR );

            /* Wait for the socket to disconnect gracefully (indicated by FreeRTOS\_recv()
               returning a -pdFREERTOS_ERRNO_EINVAL error) before closing the socket. */
            while( FreeRTOS_recv( xSocket, (char*)buf, xTotalLengthToSend, 0 ) >= 0 )
            {
                /* Wait for shutdown to complete. If a receive block time is used then
                   this delay will not be necessary as FreeRTOS_recv() will place the RTOS task
                   into the Blocked state anyway. */
                vTaskDelay( pdTICKS_TO_MS( 250 ) );

                /* Note - real applications should implement a timeout here, not just
                   loop forever. */
            }

            /* The socket has shut down and is safe to close. */
            FreeRTOS_closesocket( xSocket );
        }

		/* Pause for a short while to ensure the network is not too congested. */
        #define echoLOOP_DELAY	( ( TickType_t ) 150 / portTICK_PERIOD_MS )
		vTaskDelay( echoLOOP_DELAY );
    }
}

Hi @slhuan,

It appears that in this code segment, the TCP 3-way handshake is initiated by FreeRTOS_connect(), but the FreeRTOS_send part isn’t executed due to conditional statements.

For more information on sending TCP data, you might find our official documentation helpful: Sending Data Using a TCP Socket - FreeRTOS™

Thank you.

so if i want to send a tcp socket, i should do “create a socket->connect to server->send socked->shut down->close socket” every time?

That depends on your use case. You can also keep the connection alive till you don’t need it anymore. Then the flow would be like:

  1. Establish connection: create a socket -> connect to server
  2. Loop to send data: send socket via socket handler created at step 1
  3. Close when you don’t need the connection: shut down -> close socket

Actually i do not close the connection after the task start run. I create a tcp socket and then bind to a ip address and port, wait for connecting to server. And then send socket data in a loop, like my code did.But wireshark shows that MCU send a TCP spurious retransmission.
So I don’t know what should I do after call FreeRTOS_send() so that I could send other socket data.

On your snapshot, the device doesn’t send many packets like the wireshark shows.
May I know how many interfaces you’re capturing on the wireshark? If you’re capturing multiple interfaces, could you specify only one to avoid some duplications?
And is the connection working as expectation? Or the device never sends tha packet other than 3-way HS?

Thank you.

I capture only one interface, and add a filter “ip.addr ==192.168.50.121”.
MCU has been connected to computer TCP server, and server also received a socket “Hello World” but only one time.
Wireshar show that MCU send a retransmission immediately after call FreeRTOS_send() transmiting first socket.

Freertos_send_spurious_retransmission.zip (992.1 KB)

I’ve discovered what caused this problem.
In <freertosipconfig.h>, I defined “#define ipconfigIP_TASK_STACK_SIZE_WORDS ( configMINIMAL_STACK_SIZE * 2 )”, maybe it is so big?

That depends on the device. If your device is out-of-memory, it may cause some unexpected behavior. Thanks for reporting back! Happy to know that it’s working!