Example #1
0
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 );
	}
}