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:
TCP Client Web Interface
Application Source Code
The application consists of the following source files:
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 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)
{
}
}
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>
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 <fdprintf.h>
#include "clientweb.h"
#define APP_VERSION "Version 1.2 9/1/2018"
#define POST_BUFSIZE (4096) // form post buffer size
int gDestPort;
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 );
}
}
{
if ( gDestPort == 0 )
gDestPort = 2000;
fdprintf(sock, "VALUE=\"%d\" ", gDestPort);
}
{
fdprintf( sock, "VALUE=\"%I\" ", GetSocketRemoteAddr(sock) );
else
fdprintf( sock, "VALUE=\"%I\" ", gDestIp );
}
void WebShowClientIp(int sock, PCSTR url)
{
fdprintf( sock, "%I", GetSocketRemoteAddr(sock));
}
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 );
}
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 in dotted notation (eg. 192.168.1.1).