DWORD WINAPI prvSimpleWinsockTCPClientTask( void *pvParameters ) { char *pcTransmittedString, *pcReceivedString; BaseType_t lReceived, lTransmitted = 0, lStringLength, lReturned = 0, lInstance; uint32_t ulCount = 0UL, ulMaxCount, ulIPAddress; const uint32_t ulMaxLoopsPerSocket = 100UL; struct sockaddr_in xConnection; SOCKET xClientSocket; int iReturned; TickType_t xTimeOnShutdown; /* Multiple instances of this task are created. The instance is passed in as the parameter. */ lInstance = ( BaseType_t ) pvParameters; /* Locate the buffers for this instance of this task. */ pcTransmittedString = &( cTxBuffers[ lInstance ][ 0 ] ); pcReceivedString = &( cRxBuffers[ lInstance ][ 0 ] ); /* It is assumed that this task is not created until the network is up, so the IP address of the server (which is the FreeRTOS+TCP side of the connection) can be obtained immediately. Store the IP address being used in ulIPAddress. */ FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL ); /* Set family and port for client socket. */ memset( ( void * ) &xConnection, 0x00, sizeof( struct sockaddr_in ) ); xConnection.sin_family = AF_INET; xConnection.sin_addr.s_addr = ulIPAddress; xConnection.sin_port = htons( tcpechoPORT_NUMBER ); for( ;; ) { /* Create the socket then connect it to the FreeRTOS+TCP server. */ xClientSocket = socket( AF_INET, SOCK_STREAM, 0 ); configASSERT( xClientSocket != INVALID_SOCKET ); do { iReturned = connect( xClientSocket, (const struct sockaddr*) &xConnection, sizeof( xConnection ) ); } while( iReturned != 0 ); ulMaxCount = ipconfigRAND32() % ulMaxLoopsPerSocket; for( ulCount = 0; ulCount < ulMaxCount; ulCount++ ) { /* Create a string then send it to the server. */ lStringLength = prvCreateTxData( pcTransmittedString, tcpechoBUFFER_SIZE ); lTransmitted = send( xClientSocket, pcTransmittedString, lStringLength, 0 ); configASSERT( lTransmitted != SOCKET_ERROR ); configASSERT( lTransmitted == lStringLength ); if( lTransmitted == lStringLength ) { memset( ( void * ) pcReceivedString, 0x00, tcpechoBUFFER_SIZE ); lReceived = 0; /* Wait for the echoed string. */ while( lReceived < lTransmitted ) { lReturned = recv( xClientSocket, ( char * ) &( pcReceivedString[ lReceived ] ), lTransmitted - lReceived, 0 ); if( lReturned >= 0 ) { /* Data was received. */ lReceived += lReturned; } else { /* Error was returned. */ ulClientReceiveErrors++; break; } } /* If the socket was not closed, check the number of bytes received. */ if( lReceived == lTransmitted ) { /* Were the expected characters received? */ configASSERT( memcmp( pcTransmittedString, pcReceivedString, lTransmitted ) == 0x00 ); if( memcmp( pcTransmittedString, pcReceivedString, lReceived ) != 0x00 ) { ulIncorrectDataReceived++; break; } else { /* Received expected string, increment the count of successful cycles. */ ulClientCycles++; } } else { /* Socket is being closed or an error occurred. Don't try using the same socket again. */ break; } } else { ulClientTransmitErrors++; break; } } shutdown( xClientSocket, SD_BOTH ); xTimeOnShutdown = xTaskGetTickCount(); do { Sleep( tcpechoWINSOCK_SHUTDOWN_DELAY ); lReturned = recv( xClientSocket, pcReceivedString, lTransmitted, 0 ); if( lReturned < 0 ) { break; } } while( ( xTaskGetTickCount() - xTimeOnShutdown ) < tcpechoSHUTDOWN_DELAY ); configASSERT( closesocket( xClientSocket ) == 0 ); Sleep( tcpechoLOOP_DELAY ); } }
static void prvEchoClientTask( void *pvParameters ) { Socket_t xSocket; struct freertos_sockaddr xEchoServerAddress; int32_t lLoopCount = 0UL; const int32_t lMaxLoopCount = 1; volatile uint32_t ulTxCount = 0UL; BaseType_t xReceivedBytes, xReturned, xInstance; BaseType_t lTransmitted, lStringLength; char *pcTransmittedString, *pcReceivedString; WinProperties_t xWinProps; TickType_t xTimeOnEntering; /* Fill in the buffer and window sizes that will be used by the socket. */ xWinProps.lTxBufSize = 6 * ipconfigTCP_MSS; xWinProps.lTxWinSize = 3; xWinProps.lRxBufSize = 6 * ipconfigTCP_MSS; xWinProps.lRxWinSize = 3; /* This task can be created a number of times. Each instance is numbered to enable each instance to use a different Rx and Tx buffer. The number is passed in as the task's parameter. */ xInstance = ( BaseType_t ) pvParameters; /* Point to the buffers to be used by this instance of this task. */ pcTransmittedString = &( cTxBuffers[ xInstance ][ 0 ] ); pcReceivedString = &( cRxBuffers[ xInstance ][ 0 ] ); /* Echo requests are sent to the echo server. The address of the echo server is configured by the constants configECHO_SERVER_ADDR0 to configECHO_SERVER_ADDR3 in FreeRTOSConfig.h. */ xEchoServerAddress.sin_port = FreeRTOS_htons( echoECHO_PORT ); xEchoServerAddress.sin_addr = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0, configECHO_SERVER_ADDR1, configECHO_SERVER_ADDR2, configECHO_SERVER_ADDR3 ); for( ;; ) { /* Create a TCP socket. */ xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, 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 ) ); /* Set the window and buffer sizes. */ FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps, sizeof( xWinProps ) ); /* Connect to the echo server. */ if( FreeRTOS_connect( xSocket, &xEchoServerAddress, sizeof( xEchoServerAddress ) ) == 0 ) { ulConnections[ xInstance ]++; /* Send a number of echo requests. */ for( lLoopCount = 0; lLoopCount < lMaxLoopCount; lLoopCount++ ) { /* Create the string that is sent to the echo server. */ lStringLength = prvCreateTxData( pcTransmittedString, echoBUFFER_SIZES ); /* Add in some unique text at the front of the string. */ sprintf( pcTransmittedString, "TxRx message number %u", ulTxCount ); ulTxCount++; /* Send the string to the socket. */ lTransmitted = FreeRTOS_send( xSocket, /* The socket being sent to. */ ( void * ) pcTransmittedString, /* The data being sent. */ lStringLength, /* The length of the data being sent. */ 0 ); /* No flags. */ if( lTransmitted < 0 ) { /* Error? */ break; } /* Clear the buffer into which the echoed string will be placed. */ memset( ( void * ) pcReceivedString, 0x00, echoBUFFER_SIZES ); xReceivedBytes = 0; /* Receive data echoed back to the socket. */ while( xReceivedBytes < lTransmitted ) { xReturned = FreeRTOS_recv( xSocket, /* The socket being received from. */ &( pcReceivedString[ xReceivedBytes ] ),/* The buffer into which the received data will be written. */ lStringLength - xReceivedBytes, /* The size of the buffer provided to receive the data. */ 0 ); /* No flags. */ if( xReturned < 0 ) { /* Error occurred. Latch it so it can be detected below. */ xReceivedBytes = xReturned; break; } else if( xReturned == 0 ) { /* Timed out. */ break; } else { /* Keep a count of the bytes received so far. */ xReceivedBytes += xReturned; } } /* If an error occurred it will be latched in xReceivedBytes, otherwise xReceived bytes will be just that - the number of bytes received from the echo server. */ if( xReceivedBytes > 0 ) { /* Compare the transmitted string to the received string. */ configASSERT( strncmp( pcReceivedString, pcTransmittedString, lTransmitted ) == 0 ); if( strncmp( pcReceivedString, pcTransmittedString, lTransmitted ) == 0 ) { /* The echo reply was received without error. */ ulTxRxCycles[ xInstance ]++; } else { /* The received string did not match the transmitted string. */ ulTxRxFailures[ xInstance ]++; break; } } else if( xReceivedBytes < 0 ) { /* FreeRTOS_recv() returned an error. */ break; } else { /* Timed out without receiving anything? */ break; } } /* Finished using the connected socket, initiate a graceful close: FIN, FIN+ACK, ACK. */ FreeRTOS_shutdown( xSocket, FREERTOS_SHUT_RDWR ); /* Expect FreeRTOS_recv() to return an error once the shutdown is complete. */ xTimeOnEntering = xTaskGetTickCount(); do { xReturned = FreeRTOS_recv( xSocket, /* The socket being received from. */ &( pcReceivedString[ 0 ] ), /* The buffer into which the received data will be written. */ echoBUFFER_SIZES, /* The size of the buffer provided to receive the data. */ 0 ); if( xReturned < 0 ) { break; } } while( ( xTaskGetTickCount() - xTimeOnEntering ) < xReceiveTimeOut ); } /* Close this socket before looping back to create another. */ FreeRTOS_closesocket( xSocket ); /* Pause for a short while to ensure the network is not too congested. */ vTaskDelay( echoLOOP_DELAY ); } }