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.
#include <predef.h>
#include <stdio.h>
#include <startnet.h>
#include <ipshow.h>
#include "clientweb.h"
void UserMain(void * pd)
{
showIpAddresses();
RegisterPost();
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.
#include <predef.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <utils.h>
#include <string.h>
#include "clientweb.h"
#define APP_VERSION "Version 1.2 9/1/2018"
#define POST_BUFSIZE (4096)
int gDestPort;
void SendMsg(
IPADDR destIp,
int destPort,
char *msg )
{
iprintf( "Connecting to: %I:%d\r\n", destIp, destPort );
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 );
}
}
void WebDestPort(int sock, PCSTR url)
{
if ( gDestPort == 0 )
gDestPort = 2000;
fdprintf(sock,
"VALUE=\"%d\" ", gDestPort);
}
void WebDestIp(int sock, PCSTR url)
{
else
fdprintf( sock,
"VALUE=\"%I\" ", gDestIp );
}
void WebShowClientIp(int sock, PCSTR url)
{
}
int MyDoPost(int sock, char * url, char * pData, char * rxBuffer)
{
int max_chars = 40;
static char buf[POST_BUFSIZE];
iprintf( "Post Data: %s\r\n", pData );
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 );
}
return 0;
}
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.
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".