NetBurner 3.5.0
PDF Version
 
TCP Client

The previous section demonstrated how a TCP Server waits for incoming connections from a TCP client. This section will demonstrate how a TCP client initiates a connection using the connect() function. Features of this example:

  • A web page interface is created with input fields for the destination IP address, destination port number, and the message to send to the server
  • Demonstrates how to use HTML forms to submit user data
  • The web page interface will use the connect() function to create an outgoing connection to a TCP Server, send the message, and close the socket

A screen shot of the running application is shown below:





Application Source Code

The application consists of the following source files:

File Name Description
main.cpp Application initialization, starts the web server
clientweb.h Header file for clientweb.cpp
clientweb.cpp Handles the user interface interaction, makes the outgoing connection
index.html HTML code for the user interface



main.cpp

This is a very simple source file that initializes the system. All the action occurs in clientweb.cpp when a user posts web form data. The purpose of the RegisterPost() function is to use our own POST handler instead of just calling the system POST handler.

/*-------------------------------------------------------------------
This program demonstrates how to create a TCP Client. All interaction is
through the web page interface, which enables you to type a message as
well as the IP address and port number of the destination TCP server.
You should be able to use any TCP server. If you do not have one,
we have a windows example TCP server in the \nburn\pctools\TCP\TcpServerWin
directory (as well as source code).
-------------------------------------------------------------------*/
#include <predef.h>
#include <stdio.h>
#include <startnet.h>
#include <init.h>
#include <ipshow.h>
#include "clientweb.h"
void UserMain(void * pd)
{
init(); // Initialize system
StartHttp(); // Start web server
showIpAddresses(); // Display IP information to serial port
RegisterPost(); // Register custom HTML Post function
while (1)
{
}
}
#define TICKS_PER_SECOND
System clock ticks per second.
Definition nbrtos/include/constants.h:41
void OSTimeDly(uint32_t to_count)
Delay the task until the specified value of the system timer ticks. The number of system ticks per se...
Definition nbrtos.h:1732
void StartHttp(uint16_t port, bool RunConfigMirror)
Start the HTTP web server. Further documentation in the Initialization section Initialization - Syste...
void init()
System initialization. Ideally called at the beginning of all applications, since the easiest Recover...
bool WaitForActiveNetwork(uint32_t ticks_to_wait=120 *TICKS_PER_SECOND, int interface=-1)
Wait for an active network connection on at least one interface.
NetBurner System Initialization Header File.

clientweb.h

The only function we need to call outside of clientweb.cpp is RegisterPost()

#ifndef _NB_CLIENTWEB_H
#define _NB_CLIENTWEB_H
void RegisterPost();
#endif

index.html

Web page implements a form to send data to the TCP server using a web POST. Inside the HTML <form> tags there is a table for formatting, with three HTML <input> fields. The message input field is straight HTML and any data entered in the text box will be sent to the server as data in the POST. The second and third input fields make use of the NetBurner CPPCALL function callback tag to execute functions that provide default values in the input fields when the page is displayed.

<html>
<head>
<title>NetBurner TCP Client Example Program</title>
</head>
<img src="logo.jpg">
<br>
<h1>TCP Client Example Program</h1>
This example program will open a TCP connection to a TCP Server at
the specified IP address and send a message. A simple TCP Server,
TcpServerWin.exe, is included in the \nburn\pctools directory.
<form ACTION="nothing.html" METHOD=POST><br>
<table>
<tr>
<td>Enter Message to send: </td>
<td><input NAME="tfMessage" TYPE="text" SIZE="30"></td>
</tr>
<tr>
<td>Destination Port: </td>
<td><input NAME="tfDestPortNum" <!--CPPCALL WebDestPort --> TYPE="text" SIZE="6"></td>
</tr>
<tr>
<td>Destination IP: </td>
<td><input NAME="tfDestIpAddr" <!--CPPCALL WebDestIp --> TYPE="text" SIZE="15">
(Your IP address is: <!--CPPCALL WebShowClientIp --> )
</td>
</tr>
<tr>
<td> <br></td>
</tr>
<tr>
<td><input NAME="SendMessage" TYPE="submit" VALUE="Send Message"></td>
</tr>
<br><br>
</table>
</form>
</body>
</html>
@ NAME
"xxx": - Signals the name of a name/value pair.
Definition json_lexer.h:66

clientweb.cpp

This code module handles the dynamic content and web server interface. When the web page is displayed, current values for the port numbers and IP addresses are filled in as default values.

/*-------------------------------------------------------------------
* This code implements the web page entries for the message,
* destination IP address and destination port number. When the
* web page first loads it will automatically fill in the IP
* address from the source requesting the web page, because in
* most cases it will also be the address of the TCP Server.
* The web page is a form, and when a user presses the submit
* button the SendMsg() function will open a TCP connection to
* the server, send the message, and close the connection.
* Any error messages will be sent to stdout and can be viewed
* with MTTTY.
*
* A TCP server program must already be listening at the specified
* IP address and port number for the message to be sent. A simple
* TCP Server called TcpServerWin.exe is located in the
* \nburn\pctools directory of your NetBurner installation.
-------------------------------------------------------------------*/
#include <predef.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <http.h>
#include <iosys.h>
#include <utils.h>
#include <tcp.h>
#include <string.h>
#include <fdprintf.h>
#include "clientweb.h"
#define APP_VERSION "Version 1.2 9/1/2018"
#define POST_BUFSIZE (4096) // form post buffer size
int gDestPort;
IPADDR gDestIp;
/*-------------------------------------------------------------------
Sends a message to the specified host.
------------------------------------------------------------------*/
void SendMsg( IPADDR destIp, int destPort, char *msg )
{
iprintf( "Connecting to: %I:%d\r\n", destIp, destPort );
int fd = connect( destIp, destPort, TICKS_PER_SECOND * 5 );
if (fd < 0)
{
iprintf("Error: Connection failed\r\n");
}
else
{
iprintf( "Attempting to write: \"%s\" \r\n", msg );
int n = write( fd, msg, strlen(msg) );
iprintf( "Wrote %d bytes\r\n", n );
close( fd );
}
}
/*-------------------------------------------------------------------
* Show destination port number on web page
* ----------------------------------------------------------------*/
void WebDestPort(int sock, PCSTR url)
{
if ( gDestPort == 0 ) // If no dest port is specified, use a default
gDestPort = 2000;
fdprintf(sock, "VALUE=\"%d\" ", gDestPort);
}
/*-------------------------------------------------------------------
Show destination ip address on web page
------------------------------------------------------------------*/
void WebDestIp(int sock, PCSTR url)
{
if ( gDestIp.IsNull() ) // If no dest ip address has been entered, use the one that requested the web page.
fdprintf( sock, "VALUE=\"%I\" ", GetSocketRemoteAddr(sock) );
else
fdprintf( sock, "VALUE=\"%I\" ", gDestIp );
}
/*-------------------------------------------------------------------
* Show destination ip address on web page
*------------------------------------------------------------------*/
void WebShowClientIp(int sock, PCSTR url)
{
fdprintf( sock, "%I", GetSocketRemoteAddr(sock));
}
/*-------------------------------------------------------------------
* Process HTTP Post
*------------------------------------------------------------------*/
int MyDoPost(int sock, char * url, char * pData, char * rxBuffer)
{
int max_chars = 40;
// The buffer is 4096 bytes, make it static so that it does
// not take up task stack space, but instead uses global space.
static char buf[POST_BUFSIZE];
iprintf( "Post Data: %s\r\n", pData ); // print all data sent from app
// The SendMessage button on the web page initiates a form POST to send the message to the TCP server.
if ( ExtractPostData( "SendMessage", pData, buf, max_chars) > 0 )
{
iprintf( "Processing SendMessage Post\r\n" );
if (ExtractPostData("tfDestPortNum", pData, buf, max_chars) == -1)
iprintf("Error reading post data: tfDestPortNum\r\n");
else
gDestPort = (int)atoi(buf);
if (ExtractPostData("tfDestIpAddr", pData, buf, max_chars) == -1)
iprintf( "Error reading post data: tfDestIpAddr\r\n");
else
gDestIp = AsciiToIp( buf );
if ( ExtractPostData( "tfMessage", pData, buf, max_chars ) < 0 )
iprintf("Error reading post data: tfMessage\r\n");
else
SendMsg( gDestIp, gDestPort, buf );
}
// We have to respond to the post with a new HTML page. In this case we
// will redirect so the browser will go to that URL for the response.
RedirectResponse( sock, "index.htm" );
return 0;
}
/*-------------------------------------------------------------------
Specify the function to call when a user clicks Submit on the
web page form.
------------------------------------------------------------------*/
void RegisterPost()
{
SetNewPostHandler( MyDoPost );
}
Used to hold and manipulate IPv4 and IPv6 addresses in dual stack mode.
Definition ipv6_addr.h:41
bool IsNull() const
Check if the IP address is null.
Definition ipv6_addr.h:101
NetBurner functions to printf to a file descriptor.
int fdprintf(int fc, const char *format,...)
printf to a file descriptor
int close(int fd)
Close the specified file descriptor and free the associated resources.
int write(int fd, const char *buf, int nbytes)
Write data to the stream associated with a file descriptor (fd). Can be used to write data to stdio,...
int connect(const IPADDR &ipAddress, uint16_t remotePort, uint32_t timeout)
Make an outgoing TCP connection to a remote host.
Definition tcp.h:112
IPADDR GetSocketRemoteAddr(int fd)
Returns the IP address of the remote host associated with the specified file descriptor.
Definition tcp.h:638
void RedirectResponse(int sock, PCSTR new_page)
Redirect a HTTP request to a different page.
NetBurner HTTP Web Server Header File.
NetBurner I/O System Library API.
NetBurner TCP API.

TCP Client Program Operation

The application boots and executes the initialization functions in main.cpp. From that point forward all interaction occurs through the web interface. When a client web browser connects to the device's web server, the CPPCALL functions WebDestPort() and WebDestIp() fill in the current values in the input text fields. A port number of 2000 is specified as the default port. The WebDestIp() function will default to the last value entered by the user, or if no value has been entered yet, it will enter the IP address of the host running the web browser. It extracts the IP address from the TCP connection request.

The message to send it is just a temporary string displayed in the web browser. To send a message, the user clicks on the Send Message submit button. This is a HTML command that sends a web POST to the web server containing all the information contained in the form. This is where the MyDoPost() function in clientweb.cpp comes into play. It parses the POST data, assigns data tot he runtime variables, extracts the message data, and calls SendMsg(). SendMsg() in clientweb.cpp makes a connect() call using the passed message and the values of the destination port number and IP address. Once the connection is made, SendMsg() calls write() to send the message followed by close() to terminate the connection.

Note
The "%I" parameter in the iprintf() functions will display an IP addresses for an IPADDR object in dotted notation (eg. 192.168.1.1). An IPADDR object can hold an IPv4 or IPv6 address. For IPADDR4 objects, use "%hI".