To be frank, building simple networking programs with the assistance of AJAX can be done without minor problems. It’s possible to create a friendly front-end which can interact with the server via JavaScript to run different network utilities.
Part of this process was profusely explained in the first part of the series, where I went through the development of a basic graphical interface. The interface provided users with a group of buttons and an input box for running several queries against a selected Internet host.
Also, among the decent variety of network utilities that can be performed by this application, you can find the popular “ipconfig” and “netstat” commands (available on Windows-based systems), scanning TCP ports, searching DNS records, and many more. So the program in question can be used at least to perform basic tasks in real networking environments. That's pretty good, considering that all these processes are executed using only a web browser!
All right, now that you hopefully recall all the topics that were treated over the course of the preceding article, let me tell you what you’ll learn in this new tutorial. As you’ll probably remember, even when the user interface that corresponds to this application was completely developed, the group of JavaScript functions responsible for sending out queries in the background, along with displaying eventual results, remained undefined.
That’s precisely the subject of this second article of the series. In the next few lines, I’m going to show you how to define some simple JavaScript functions aimed at querying a given Internet host and returning the potential results to the browser.
This educational journey is just about to begin. Want to see how this story continues? Okay, let’s do it together!
Before I define all the JavaScript functions that comprise the behavioral layer of the networking application in question, let me first list its complete client-side code, as originally defined in the first part of the series.
Here is the corresponding code listing:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-
8859-1" />
<title>AJAX-based Networking Processor</title>
<style type="text/css">
body{
padding: 0;
margin: 0;
background: #fff;
}
h1{
font: bold 24px Arial, Helvetica, sans-serif;
color: #000;
text-align: center;
margin: 10px;
}
#maincontainer{
width: 500px;
height: 400px;
background: #eee;
padding: 5px;
margin-left: auto;
margin-right: auto;
border: 1px solid #000;
}
#paramcontainer{
padding: 5px;
margin-bottom: 5px;
background: #f5ebb1;
font: bold 12px Arial, Helvetica, sans-serif;
color: #000;
border: 1px solid #999;
}
#leftpanel{
float: left;
width: 100px;
height: 350px;
padding: 5px;
background: #f5ebb1;
font: bold 12px Arial, Helvetica, sans-serif;
color: #000;
border: 1px solid #999;
}
#centerpanel{
float: left;
width: 254px;
height: 350px;
padding: 5px;
margin-left: 5px;
background: #ccc;
overflow: auto;
font: bold 12px Arial, Helvetica, sans-serif;
color: #000;
border: 1px solid #999;
}
#rightpanel{
float: right;
width: 100px;
height: 350px;
padding: 5px;
background: #f5ebb1;
font: bold 12px Arial, Helvetica, sans-serif;
color: #000;
border: 1px solid #999;
}
.databox{
width: 348px;
font: normal 12px Arial, Helvetica, sans-serif;
color: #000;
}
.controlbutton{
width: 100px;
margin: 3px 0 3px 0;
font: normal 12px Arial, Helvetica, sans-serif;
color: #000;
text-align: center;
}
</style>
</head>
<body>
<h1>AJAX-BASED NETWORKING PROCESSOR</h1>
<div id="maincontainer">
<form>
<div id="paramcontainer">
Host Name/ IP Address <input type="text" name="data"
class="databox"></input>
</div>
<div id="leftpanel">
<input type="button" name="host" value="Host to IP"
class="controlbutton" title="Covert Hostname to IP
address"></input>
<input type="button" name="ip" value="IP to Host"
class="controlbutton" title="Convert IP address to
Hostname"></input>
<input type="button" name="iplist" value="IP List"
class="controlbutton" title="Retrieve IP list"></input>
<input type="button" name="ping" value="Ping"
class="controlbutton" title="Execute ping command"></input>
<input type="button" name="ipconfig" value="IP Config"
class="controlbutton" title="Execute ipconfig command"></input>
<input type="button" name="netstat" value="Netstat"
class="controlbutton" title="Execute netstat command"></input>
</div>
<div id="centerpanel"></div>
<div id="rightpanel">
<input type="button" name="mxrec" value="MX Records"
class="controlbutton" title="Retrieve MX records"></input>
<input type="button" name="servports" value="Service Ports"
class="controlbutton" title="Retrieve service ports"></input>
<input type="button" name="servnames" value="Service Names"
class="controlbutton" title="Retrieve service names"></input>
<input type="button" name="scanport" value="Scan Port 80"
class="controlbutton" title="Scan port 80"></input>
<input type="button" name="whois" value="NS Records"
class="controlbutton" title="Retrieve NS records"></input>
<input type="button" name="reset" value="Clear Panel"
class="controlbutton" title="Clear display panel"></input>
</div>
</form>
</div>
</body>
</html>
In this case, I won’t bore you with irrelevant details concerning the client-side code listed above. The only thing to stress here (just in case you haven’t read the first tutorial), is that the previous file is tasked with displaying the simple graphical interface that allows users to send queries to a selected Internet host. Quite simple, right?
Now that you understand the functionality of the previous (X)HTML file, let me go one step further and show you the first two JavaScript functions included with this networking application. These functions will take care of sending out queries in the background and displaying their eventual results in the client.
To learn how this pair of JavaScript functions will be defined, please read the following section.
As you may have guessed, to query a selected Internet host in the background it’s necessary to define a JavaScript function that allows the use of an HTTP requester object. In this way the corresponding requests can be adequately processed by the web server on its side.
Of course, this task will be performed by the function below, which I named “sendHttpRequest().” Its signature is as follows:
// send http requests
function sendHttpRequest(url,callbackFunc,respXml){
var xmlobj=null;
try{
xmlobj=new XMLHttpRequest();
}
catch(e){
try{
xmlobj=new
ActiveXObject("Microsoft.XMLHTTP");
}
catch(e){
alert('AJAX is not
supported by your browser!');
return false;
}
}
xmlobj.onreadystatechange=function(){
if(xmlobj.readyState==4){
if
(xmlobj.status==200){
respXml?eval
(callbackFunc+'(xmlobj.responseXML)'):eval
(callbackFunc+'(xmlobj.responseText)');
}
}
}
// open socket connection
xmlobj.open('GET',url,true);
// send http header
xmlobj.setRequestHeader('Content-Type','text/html;
charset=UTF-8');
// send http request
xmlobj.send(null);
}
In this particular case, the above function will send the mentioned HTTP requests via an asynchronous call, using the “GET” method. Additionally, each time a request is triggered, a command variable will be passed via the query string, which will be processed accordingly by the server.
Logically, the reason for using the mentioned variable is simply to provide the server with the ability to determine what type of query must be executed. But I'm getting ahead of myself. Let me show you another relevant JavaScript function, in this case tasked with displaying the results of an eventual query. Its short definition is as follows:
// display command results
function displayCommandResults(results){
var centpanel=document.getElementById('centerpanel');
if(!centpanel){return};
centpanel.innerHTML='';
centpanel.innerHTML=results;
}
As you can see, the previous JavaScript function simply returns the results to the client, once the corresponding query has been executed in the server, in this case using the “responseText” property that belongs to the HTTP requester object in use. For this purpose, the function in question uses the DIV element identified as “centerpanel,” which was discussed adequately in the first part of the series. So far, nothing too hard to grasp, right?
At this point, I have shown you the first pair of JavaScript functions that comprise the behavioral layer of this AJAX-powered networking application. So what’s next? Well, as you’ll recall, I mentioned that each time an HTTP request is sent, a command variable is passed straight to the web server.
In response to this situation, I need to define another brand new function that not only creates the command variable that I referenced before, but also assigns “onclick” event handlers to all the query buttons included in the corresponding front-end, developed in the preceding article.
To learn how all these tasks will be carried out, please jump ahead and read the following section.
In order to assign multiple “onclick” event handlers to each of the query buttons integrated with the graphical user interface of the application, I’ll define the brand new “initializeControlPanel()” function, which performs this task.
Having explained the capacity required for this new function, have a look at its definition. It is as follows:
// initialize control panel
function initializeControlPanel(){
var form=document.getElementsByTagName('form')[0];
if(!form){return};
// assign 'onclick' event handlers to control buttons
if(!form.elements[1]){return};
form.elements[1].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=host','displayCommandResults')};
if(!form.elements[2]){return};
form.elements[2].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=ip','displayCommandResults')};
if(!form.elements[3]){return};
form.elements[3].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=iplist','displayCommandResults')};
if(!form.elements[4]){return};
form.elements[4].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=ping','displayCommandResults')};
if(!form.elements[5]){return};
form.elements[5].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=ipconfig','displayCommandResults')};
if(!form.elements[6]){return};
form.elements[6].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=netstat','displayCommandResults')};
if(!form.elements[7]){return};
form.elements[7].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=mxrecords','displayCommandResults')};
if(!form.elements[8]){return};
form.elements[8].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=serviceports','displayCommandResults')};
if(!form.elements[9]){return};
form.elements[9].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=servicenames','displayCommandResults')};
if(!form.elements[10]){return};
form.elements[10].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=scanport','displayCommandResults')};
if(!form.elements[11]){return};
form.elements[11].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=nsrecords','displayCommandResults')};
if(!form.elements[12]){return};
form.elements[12].onclick=function(){
var centpanel=document.getElementById
('centerpanel');
if(!centpanel){return};
centpanel.innerHTML='';
}
}
Although the above function seems to be hard to grasp at first glance, the truth is that its logic is very easy to understand. As you can see, the function in question is responsible for assigning an “onclick” event handler to each of the query buttons included with the respective user interface. It also triggers an HTTP request to the “query_processor.php” file each time a button is clicked on.
In addition, you should notice that every time this action is taken, the aforementioned command variable is passed to the web server, in this way indicating to it what type of query should be executed in consequence. Indeed, the previous “initializeControlPanel()” function is pretty straightforward.
Okay, now that you know how the two JavaScript functions that you learned do their things, it’s time to leap forward and see how all the parts of this networking application fit together. This will finish the entire client-side layer of the program would be finished.
So do you want to see how the complete client-side code that belongs to this application looks? Click on the link below and keep reading.
In accordance with the explanations that I gave you in the previous section, below I included the complete client-side code that corresponds to this AJAX-based networking application. Study the code listing, please:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-
8859-1" />
<title>AJAX-based Networking Processor</title>
<style type="text/css">
body{
padding: 0;
margin: 0;
background: #fff;
}
h1{
font: bold 24px Arial, Helvetica, sans-serif;
color: #000;
text-align: center;
margin: 10px;
}
#maincontainer{
width: 500px;
height: 400px;
background: #eee;
padding: 5px;
margin-left: auto;
margin-right: auto;
border: 1px solid #000;
}
#paramcontainer{
padding: 5px;
margin-bottom: 5px;
background: #f5ebb1;
font: bold 12px Arial, Helvetica, sans-serif;
color: #000;
border: 1px solid #999;
}
#leftpanel{
float: left;
width: 100px;
height: 350px;
padding: 5px;
background: #f5ebb1;
font: bold 12px Arial, Helvetica, sans-serif;
color: #000;
border: 1px solid #999;
}
#centerpanel{
float: left;
width: 254px;
height: 350px;
padding: 5px;
margin-left: 5px;
background: #ccc;
overflow: auto;
font: bold 12px Arial, Helvetica, sans-serif;
color: #000;
border: 1px solid #999;
}
#rightpanel{
float: right;
width: 100px;
height: 350px;
padding: 5px;
background: #f5ebb1;
font: bold 12px Arial, Helvetica, sans-serif;
color: #000;
border: 1px solid #999;
}
.databox{
width: 348px;
font: normal 12px Arial, Helvetica, sans-serif;
color: #000;
}
.controlbutton{
width: 100px;
margin: 3px 0 3px 0;
font: normal 12px Arial, Helvetica, sans-serif;
color: #000;
text-align: center;
}
</style>
<script language="javascript">
// send http requests
function sendHttpRequest(url,callbackFunc,respXml){
var xmlobj=null;
try{
xmlobj=new XMLHttpRequest();
}
catch(e){
try{
xmlobj=new
ActiveXObject("Microsoft.XMLHTTP");
}
catch(e){
alert('AJAX is not
supported by your browser!');
return false;
}
}
xmlobj.onreadystatechange=function(){
if(xmlobj.readyState==4){
if(xmlobj.status==200){
respXml?eval
(callbackFunc+'(xmlobj.responseXML)'):eval
(callbackFunc+'(xmlobj.responseText)');
}
}
}
// open socket connection
xmlobj.open('GET',url,true);
// send http header
xmlobj.setRequestHeader('Content-Type','text/html;
charset=UTF-8');
// send http request
xmlobj.send(null);
}
// display command results
function displayCommandResults(results){
var centpanel=document.getElementById('centerpanel');
if(!centpanel){return};
centpanel.innerHTML='';
centpanel.innerHTML=results;
}
// initialize control panel
function initializeControlPanel(){
var form=document.getElementsByTagName('form')[0];
if(!form){return};
// assign 'onclick' event handlers to control buttons
if(!form.elements[1]){return};
form.elements[1].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=host','displayCommandResults')};
if(!form.elements[2]){return};
form.elements[2].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=ip','displayCommandResults')};
if(!form.elements[3]){return};
form.elements[3].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=iplist','displayCommandResults')};
if(!form.elements[4]){return};
form.elements[4].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=ping','displayCommandResults')};
if(!form.elements[5]){return};
form.elements[5].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=ipconfig','displayCommandResults')};
if(!form.elements[6]){return};
form.elements[6].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=netstat','displayCommandResults')};
if(!form.elements[7]){return};
form.elements[7].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=mxrecords','displayCommandResults')};
if(!form.elements[8]){return};
form.elements[8].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=serviceports','displayCommandResults')};
if(!form.elements[9]){return};
form.elements[9].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=servicenames','displayCommandResults')};
if(!form.elements[10]){return};
form.elements[10].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=scanport','displayCommandResults')};
if(!form.elements[11]){return};
form.elements[11].onclick=function(){sendHttpRequest
('query_processor.php?data='+document.getElementsByTagName
('form')[0].elements
[0].value+'&command=nsrecords','displayCommandResults')};
if(!form.elements[12]){return};
form.elements[12].onclick=function(){
var centpanel=document.getElementById
('centerpanel');
if(!centpanel){return};
centpanel.innerHTML='';
}
}
// execute 'initializeControlPanel()' function when web page is
loaded
window.onload=function(){
if(document.getElementById&&document.
getElementsByTagName&&document.createElement){
initializeControlPanel();
}
}
</script>
</head>
<body>
<h1>AJAX-BASED NETWORKING PROCESSOR</h1>
<div id="maincontainer">
<form>
<div id="paramcontainer">
Host Name/ IP Address <input type="text" name="data"
class="databox"></input>
</div>
<div id="leftpanel">
<input type="button" name="host" value="Host to IP"
class="controlbutton" title="Covert Hostname to IP
address"></input>
<input type="button" name="ip" value="IP to Host"
class="controlbutton" title="Convert IP address to
Hostname"></input>
<input type="button" name="iplist" value="IP List"
class="controlbutton" title="Retrieve IP list"></input>
<input type="button" name="ping" value="Ping"
class="controlbutton" title="Execute ping command"></input>
<input type="button" name="ipconfig" value="IP Config"
class="controlbutton" title="Execute ipconfig command"></input>
<input type="button" name="netstat" value="Netstat"
class="controlbutton" title="Execute netstat command"></input>
</div>
<div id="centerpanel"></div>
<div id="rightpanel">
<input type="button" name="mxrec" value="MX Records"
class="controlbutton" title="Retrieve MX records"></input>
<input type="button" name="servports" value="Service Ports"
class="controlbutton" title="Retrieve service ports"></input>
<input type="button" name="servnames" value="Service Names"
class="controlbutton" title="Retrieve service names"></input>
<input type="button" name="scanport" value="Scan Port 80"
class="controlbutton" title="Scan port 80"></input>
<input type="button" name="whois" value="NS Records"
class="controlbutton" title="Retrieve NS records"></input>
<input type="button" name="reset" value="Clear Panel"
class="controlbutton" title="Clear display panel"></input>
</div>
</form>
</div>
</body>
</html>
That’s all the client-side code that you need to have a near-to-completion AJAX networking processor! As usual, feel free to incorporate your own changes to the previous (X)HTML file so you can modify the visual appearance of application’s user interface. I’m sure you’ll have a good time!
Final thoughts
Over this second installment of the series, I demonstrated in a few easy steps how to create the JavaScript functions which are needed for sending out queries in the background and displaying the results. As you can see, the AJAX-based network application is almost finished.
Nevertheless, I saved the best for last. In the final article I’ll show you how to integrate all the client-side code that you have learned so far with a full-featured PHP networking class to turn the program into a completely-functional piece of software. You won't want to miss it.