Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

small client/server using sockets inputting through jsp

Status
Not open for further replies.

limecake

Technical User
Apr 30, 2005
5
AU
I'm having problems with the following whenever a cd is inputted via cdinput.html it runs cdprocess.jsp to create an XML document with DOM in memory this is sent to the server and is later printed out to the users screen. The server must be started in order for it to work. For some reason it doesn't seem to be working? In cd process i'm suppose to modify a few things they've been numbered i've complete all of them so far but i'm not sure if #4 is correct. I've been stuck on it for a while now, any help would be appreciated.

cdinput.html

<html>
<head><title></title></head>
<body>

<br /><center>
<table width="500" border="0"
cellpadding="4" cellspacing="0">
<tr>
<td bgcolor="lightblue">
<font color="white" face="Arial"><b>CD Input</b>
</font></td>
</tr>

<tr>
<td>
<form method="post" action="cdprocess.jsp">
<table>
<tr>
<td><b>CD Title:</b></td>
<td><input type="text" name="cdtitle" size="20"></td>
</tr>
<tr>
<td><b>CD Artist:</b></td>
<td><input type="text" name="cdartist" size="20"></td>
</tr>
<tr>
<td><b>Track 1 title:</b></td>
<td><input type="text" name="track1title" size="20"></td>
</tr>
<tr>
<td><b>Track 1 time:</b></td>
<td><input type="text" name="track1time" size="20"></td>
</tr>
<tr>
<td><b>Track 1 rating:</b></td>
<td><select name="track1rating">
<option value="1"> 1 </option>
<option value="2"> 2 </option>
<option value="3"> 3 </option>
<option value="4"> 4 </option>
<option value="5"> 5 </option>
</select></td>
</tr>
</table><br />
<input type="submit" value="Enter CD">
</form>
</td>
</tr>

</table>
</center>
</body>
</html>


SimpleServer2.java


import java.net.*;
import java.io.*;

/**
The server half of a simple client/server application.
The server that reads lines of text from a socket and sends
back a copy of the same text to the client.

The main difference between this example and SimpleServer is that
this one allows multiple sequential (not concurrent) connections
from clients.

public class SimpleServer2 {


public static final int serverListenPort = 10151;


/**
The main method is the entry point for the application.
Because this is a simple application for testing, everything
is done inside the main method.

@param args Arguments entered on the command-line.
*/
public static void main(String[] args) throws IOException {

ServerSocket myServerSocket = null;

// Try to open a server socket listening on specified listen port
try {
myServerSocket = new ServerSocket(serverListenPort);
}
catch (IOException e) {
System.err.println("Could not listen on port" + serverListenPort);
System.err.println("Perhaps somebody else is using that port number??");
System.exit(1);
}

/* **************************************************
* This is where the difference begins.
* Note the while(true) loop, which means that we will
* accept an infinite number of connections from clients,
* one at a time. The server will never exit by itself,
* you will have to kill it manually by typing Ctrl-C
* at the command line where it is running.
* ************************************************** */

while(true) {

// Create a variable to hold the socket that we get when a
// new client connects
Socket myClientSocket = null;

// Accept a new connection from a client
// This method call will block until a client does connect
try {
myClientSocket = myServerSocket.accept();
}
catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}

// Now that we have a socket, the reading and writing code
// is basically the same as in the client application.
// We start by getting hold of the output stream to write data
// to the socket, and the input stream to read data from the socket.
PrintWriter out = new PrintWriter(myClientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(myClientSocket.getInputStream()));

String inputLine, outputLine;

// Now use a loop to read in lines of text from the client, and
// echo them back to the client

// Note that this time we do NOT break out of the loop.
// We will just wait for the client to close the connection,
// and when it does, our inputLine will be null and then we
// will break out of the loop.
while ((inputLine = in.readLine()) != null) {
outputLine = inputLine;
out.println(outputLine);
}

// If we have broken out of the loop, we can assume that
// the input is closed. The output probably is too, but
// just in case, we'll close it anyway.
out.close();
}
}
}





cdprocess.jsp


<%@page import="java.io.*"%>
<%@page import="java.net.*"%>
<%@page import="javax.xml.parsers.*"%>
<%@page import="org.w3c.dom.*"%>
<%@page import="org.apache.xml.serialize.*"%>

<%!
public static final String serverHost = "cdserver";
public static final int serverPort = 10151;
%>

<hr />
<pre>
<%

Socket mySocket = null; // socket object
PrintWriter sockOut = null; // to send data to the socket
BufferedReader sockIn = null; // to receive data from the socket

try {

// #1 add line that creates a client socket

mySocket = new Socket(serverHost, serverPort);


// #2 add lines that create input and output streams
// attached to the socket you just created

sockOut = new PrintWriter(mySocket.getOutputStream(), true);
sockIn = new BufferedReader(new InputStreamReader(mySocket.getInputStream()));


} catch (UnknownHostException e) {
throw e; // This time the JSP can handle the exception, not us
} catch (IOException e) {
throw e; // This time the JSP can handle the exception, not us
}



String cdTitle, cdArtist, track1Title, track1Time, track1Rating;

// Retrieve the HTML form field values
cdTitle = request.getParameter("cdtitle");
cdArtist = request.getParameter("cdartist");
track1Title = request.getParameter("track1title");
track1Time = request.getParameter("track1time");
track1Rating = request.getParameter("track1rating");




/*
* Our goal is to build an XML document in memory using DOM.
* We will build it up one tree-node at a time, and when it is
* finished, we will write the whole lot out to a file on disk.
*/


/* Start of the DOM code */


// Create a new DOM factory, and from that a new DOM builder object
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();

// Note that we are creating a new (empty) document
Document document = builder.newDocument();

// The root element of our document wil be <cd>
// It gets stored as the child node of the whole document (it is the root)
Element rootElement = document.createElement("cd");
document.appendChild(rootElement);

// Create an element for the CD title called <title>
Element cdTitleElement = document.createElement("title");
// Add a text code under the <title> element with the value that
// the user entered into the title field of the web form (cdTitle)
cdTitleElement.appendChild(document.createTextNode(cdTitle));
// Place the <title> element underneath the <cd> element in the tree
rootElement.appendChild(cdTitleElement);

// Create an <artist> element with the form data, place underneath <cd>
Element cdArtistElement = document.createElement("artist");
cdArtistElement.appendChild(document.createTextNode(cdArtist));
rootElement.appendChild(cdArtistElement);


// Create a <tracklist> element and place it underneath <cd> in the tree
// Note that it has no text node associated with it (it not a leaf node)
Element trackListElement = document.createElement("tracklist");
rootElement.appendChild(trackListElement);

// In this example we only have one track, so it is not necessary to
// use a loop (in fact it is quite silly)
// But the code below is included to demonstrate how you could loop
// through and add a set of different tracks one by one if you
// needed to (although you would need to have the track data already
// stored in an array or a java.util.Vector or similar

int numTracks = 1;

for (int i=0; i<numTracks; i++) {
String trackNum = Integer.toString(i+1);

// Note that this element has an attribute associated with it that
// is the track number. It will look like: <track id="1">
// The <track> element is placed underneath <tracklist> in the tree
Element trackElement = document.createElement("track");
trackElement.setAttribute("id", trackNum);
trackListElement.appendChild(trackElement);

// Track title element called <title>, placed underneath <track>
Element trackTitleElement = document.createElement("title");
trackTitleElement.appendChild(document.createTextNode(track1Title));
trackElement.appendChild(trackTitleElement);

// Track time element called <time>, placed underneath <track>
Element trackTimeElement = document.createElement("time");
trackTimeElement.appendChild(document.createTextNode(track1Time));
trackElement.appendChild(trackTimeElement);

// Track rating element called <rating>, placed underneath <track>
Element trackRatingElement = document.createElement("rating");
trackRatingElement.appendChild(document.createTextNode(track1Rating));
trackElement.appendChild(trackRatingElement);

}


/* End of DOM code */

/* Start of serialization code */

// Create a new OutputFormat - this is something specific needed by the
// XMLSerializer class shown below. We will specify that we want the
// generated XML to be formatted with indenting so it is easy to read.
OutputFormat format = new OutputFormat();
format.setIndenting(true);

/* **********************************************************************
* **********************************************************************
* Note: the next line of code is the one change to serialization
* **********************************************************************
* ********************************************************************** */



// Create a new XMLSerializer that will be used to write out the XML
// This time we will serialize it to the socket


// #3 change this line so that it serializes to the socket,
// not to the "out" object


XMLSerializer serializer = new XMLSerializer(writer, format);

// Call the serialize() method, and pass to it out XML document
// stored in memory in a DOM tree
serializer.serialize(document);


/* End of serialization code */





// Print out a message to indicate the end of the data, and
// flush the stream so all the data gets sent now
sockOut.println("<!--QUIT-->");
sockOut.flush();

BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String fromServer;
String fromUser;


/*
#4 add a while loop that reads text from the
server socket input stream, line by line, and prints
it out to the web page, using out.println(...);

Note that because the reply from the server will contain
XML, you will need to call upon the toHTMLString() method
defined below to escape the < and > symbols so that they
will display correctly in the web browser.

Also note that as you receive the reply back from the
server, you should look out for the special <!--QUIT-->
string that will indicate when there is no more data
to receive.
*/

while ((fromServer = sockIn.readLine()) != null) {
out.println(sockIn.readLine());

// If the reply from the server said "QUIT", exit from the
// while loop by using a break statement.
if (fromServer.equals("QUIT")) {
out.println("Connection closed - good bye ...");

}

// Print the text from the server out to the user's screen
out.println("Reply from Server: " + fromServer);

// Now read a line of text from the keyboard (typed by user)
fromUser = stdIn.readLine();

// If it wasn't null, print it out to the screen, and also
// print a copy of it out to the socket
if (fromUser != null) {
out.println("Client: " + fromUser);
sockOut.println(fromUser);
}
}



// Close all the streams we have open, and then close the socket
sockOut.close();
sockIn.close();
mySocket.close();

%>

<%!
/**
This method will escape any special HTML characters in a string
of text. For example, if you are trying to print out an XML
document using a JSP, you need to escape all the '<' and '>' tags
so that the web browser will not try and treat them as HTML.

Note that generic utility code like this would usually be put into
a JavaBean, but is put in the JSP here for simplicity.

This code taken from H. Bergsten, JavaServer Pages, O'Reilly, 2001.
*/
private static String toHTMLString(String in) {
StringBuffer out = new StringBuffer();
for (int i = 0; in != null && i < in.length(); i++) {
char c = in.charAt(i);
if (c == '\'') {
out.append("'");
}
else if (c == '\"') {
out.append(""");
}
else if (c == '<') {
out.append("<");
}
else if (c == '>') {
out.append(">");
}
else if (c == '&') {
out.append("&");
}
else {
out.append(c);
}
}
return out.toString();
}
%>

</pre>
<hr />



Re: small input program (html) using sockets.
Author: spear_arrow Apr 29, 2005 8:49 PM (reply 1 of 2)
.. and also it does work but for some reason it just hangs with text that's been entered via the textfields

Re: small input program (html) using sockets.
Author: spear_arrow Apr 30, 2005 7:04 AM (reply 2 of 2)
the following also has me stumped:

// #3 change this line so that it serializes to the socket,
// not to the "out" object

i tried changing the first parameter to the socket "mySocket" but it just gives me a compilation error.
 
Change :

Code:
XMLSerializer serializer = new XMLSerializer(writer, format);
to :
Code:
XMLSerializer serializer = new XMLSerializer(sockOut, format);

May I also offer some advice :

Please do not post reams and reams of code - no one wants to read through so much unfamilar code. Try to tell us your error, post the relevant bits of code, and if you get a compilation error - don't just say "I get an error" - but post the error.

In your java code, make sure you always print stack traces - just printing out "error" does not heelp anyone.

Do you really want the server to exit if the accept() fails ? I would think probably not.

Your server is currently single-threaded - ie its accept() call is blocking until that connection is done. You normally want to have a handler class that extends Thread to deal with connections.

--------------------------------------------------
Free Database Connection Pooling Software
 
hi sedj,

XMLSerializer serializer = new XMLSerializer(sockOut, format);

i've actually tried that but the problem just gets worse, when i try to enter a cd through the html it just hangs nothing is displayed i tried leaving it for up to 10 mins.

Please do not post reams and reams of code - no one wants to read through so much unfamilar code. Try to tell us your error, post the relevant bits of code, and if you get a compilation error - don't just say "I get an error" - but post the error.

sorry about that. I think the problem is with cdprocess.jsp i wasn't too sure if i followed the commented instructions properly it doesn't seem to function correctly though i.e. i agree with changing the serializer so it serializes to the sockOut instead of "out" but nothing seems to be printed out that way where as when i had "out" at least i got something

what the code should do is read text from the server socket input stream print it out on a webpage

Do you really want the server to exit if the accept() fails ? I would think probably not

from what i understand it should be when the "while" loop equals null then theres nothing else to read from the client so it just exits.
 
I would learn how to write client/server programmes in Java first before attempting to do more sophisticated stuff.

There are several errors with your server code, as I hinted earlier :

1) If the accept() fails, you exit from the programme - that is NOT what you should do.
2) You never close the input stream.
3) You never close the socket.
4) Its not multithreaded.

I would clean up the server code, then write a simple test client to ensure you fully understand how socket IO works. Then once you have that sorted, you can go on to do your xml thing.

--------------------------------------------------
Free Database Connection Pooling Software
 
2) You never close the input stream.

that's what the client does. The server is always running waiting for incoming connections i don't see why it should close it's input stream.

3) You never close the socket.

same as above.

I would clean up the server code, then write a simple test client to ensure you fully understand how socket IO works. Then once you have that sorted, you can go on to do your xml thing.

to tell you the truth, it's a tutorial exercise i've been stuck on it for a couple of weeks now i just wanted some hints if the code i wrote below the commented #'s are correct cause i think that's where the problem is - my modification.

I've actually written a basic socket server/client and fully understand the basics. I don't think i'm suppose to modify anything besides cdprocess.jsp.
 
You say you fully understand socket programming in Java - but don't think it necessary to close the IO streams or the socket itself server side ? I would suggest a re-read of how to program sockets.

I have written numerous multi threaded servers communicating via TCP/IP in Java, and C/C++, and I can assure you it is necessary to ALWAYS clean up your server's connections.

--------------------------------------------------
Free Database Connection Pooling Software
 
but don't think it necessary to close the IO streams or the socket itself server side ?

whenever a connection establishment is made, the io streams and the socket it self is closed by the client whenever it finishes sending something. But the server still listens on the port waiting for other clients to connect which then opens another socket with input/output streams (when requested).


 
You may get away with not explicitly closing the IO streams - although this is bad practtive.

However, you still never close the Socket object. So what do you think happens to the soket file descriptor ? If you don't close the socket, the FD is not released - and after a while (usually 1024 to 2048) connections, you will blow the OS's file descriptor count. I suggest you read the java.net.SocketImpl source to see how this works in OS land.

Once again - learn how sockets work before making assumptions and judgements. I guess my 5 years experience of socket programming in multiple langauges means nothing to you !

--------------------------------------------------
Free Database Connection Pooling Software
 
However, you still never close the Socket object. So what do you think happens to the soket file descriptor ? If you don't close the socket, the FD is not released - and after a while (usually 1024 to 2048) connections, you will blow the OS's file descriptor count. I suggest you read the java.net.SocketImpl source to see how this works in OS land.

I didn't write the server code it's a task. fds, sockimpl are out of scope with what i'm trying to solve.

Once again - learn how sockets work before making assumptions and judgements. I guess my 5 years experience of socket programming in multiple langauges means nothing to you !

i wasn't judging sorry if i sounded disrespective, really i do understand from your post how badly written some of the code was posted there must be a solution to it though even if the code wasn't written properly and there is a solution to it without modifying the server/cdinput code.

I know the basics behind how to program a basic socket which is far more than enough to work with the task. Unfornately the while loop is giving me problems.

The task specifically outlines the parts i have to modify, i'd rather follow the task descriptions rather than worrying about something then that's not really required to get it working and then worry about the more advanced tasks (fds etc.)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top