Java Sockets not using J2EE

Hi,

As an outline I am in the early stages of trying to set up an IM client. I'm just in the process of trying to send more than one message via a socket from client to server and get the same message come back out to the client using just J2SE (client outline).

I can get the first message to go to the server and be spat out from the client but if I try a second message the program hangs.

I'm sure it is to do with the way the socket is formed. I did originally have a close socket command in the client program which forced me to rerun the client for every message whilst the server program worked happily in the background.

I have now removed the close command so that I could send more than one message without having to rerun the client but the server doesn't even receive it.

Any advice please?

Client

import java.io.*;

import java.net.*;

import javax.swing.*;

import java.util.StringTokenizer;

publicclass HTTPClient{

String host, path, username;

int port;

Socket s;

publicstaticvoid main (String argv[]){

//I've added this statement to the original skeleton code for those

//who are unsure of how to run the program.

if (argv.length != 1){

System.out.println("usage: java HTTPClient host:port/filepath");

System.exit(1);

}

//creates a new HTTPClient, where argv[0] is the URL.

new HTTPClient(argv[0]);

}

public HTTPClient(String url){

try{

//gets url

URL myURL =new URL(url);

//gets host

host = myURL.getHost();

//gets port

port = myURL.getPort();

if (port == -1) port = 80;;

//gets path to file

path = myURL.getPath();

//appends a / to path if no path exists

if (path.equals("")) path ="/";

s =new Socket(InetAddress.getByName(host), port);

username = JOptionPane.showInputDialog(null,"Please enter your username");

String password ="";

for(int i = username.length()-1; i >= 0; i--)//password = username backwards

{

char ch = username.charAt(i);

password += ch;

}

String password_attempt ="";//set string as empty

int count = 0;//count number of pasword attempts

while(!password_attempt.equals(password)){

password_attempt = JOptionPane.showInputDialog(null,"Please enter your password ");

count++;//increment count

if (count == 3){//if 3 tries then print error message and close program

JOptionPane.showMessageDialog(null,

"You have enter a password incorrectly 3 times",

"Login Error",

JOptionPane.ERROR_MESSAGE);

System.exit(0);

}

}

sendRequest(s.getOutputStream());

}

catch(MalformedURLException murl){

System.out.println("Badly formatted URL " + murl.getMessage());

}

catch(IOException e){

System.out.println("Problem initialising socket " + e.getMessage());

}

}

publicvoid sendRequest(OutputStream out){

String message_out;

message_out = JOptionPane.showInputDialog(null,"Please enter a message");

message_out +="\r\n\r\n";

try{

out.write(message_out.getBytes("US-ASCII"));

out.flush();

printResponse(s.getInputStream());//gets response from server

}

catch (IOException e){System.out.println(e.getMessage());

}

}

/*The basis of this method is to read in the input from the server and print

*it to the screen. It sleeps for 500 milliseconds in case the server is

*busy then starts to read in characters then prints them to screen.*/

publicvoid printResponse(InputStream in){

try{

while (in.available() <= 0)

Thread.sleep(500);

while (in.available() > 0)

System.out.print((char) in.read());

System.out.println ("");

sendRequest(s.getOutputStream());//gets a new request for the server

}

catch (IOException e){

System.out.println(e.getMessage());

}

catch (InterruptedException ie){

System.out.println("Error waiting for response " + ie.getMessage());

}

}

}

and the Server

import java.io.*;

import java.net.*;

import java.util.*;

publicclass ProjectServer{

String message_in, message_out;

publicstaticvoid main(String argv[]){

//I've added this statement for those that may be unfamiliar of how to run

//the program.

if (argv.length != 1){

System.out.println("usage: java HTTPServer port");

System.exit(1);

}

//creates a new HTTPSever, argv[0] is the port.

new ProjectServer(Integer.parseInt(argv[0]));

}

public ProjectServer(int port){

boolean listening =true;

//Socket's must be created in a try and catch block as they may generate

//exceptions, which the program must deal with.

try{

ServerSocket ss =new ServerSocket(port);

System.out.println("HTTP Server running and listening for requests...");

while (listening){

Socket mySocket = ss.accept();

//create an InputStream called 'in'

InputStream in = mySocket.getInputStream();

//pass 'in' to the readInput method

readInput(in);

//create an OutputStream called 'out'

OutputStream out = mySocket.getOutputStream();

message_out = message_in;

System.out.println("I'm here");

//transform 'response' into bytes ready for output

out.write(message_out.getBytes("US-ASCII"));

//flush data out of socket

out.flush();

//close socket

//mySocket.close();

}

}

catch(Exception e){

System.out.println(e.getMessage());

}

}

privatevoid readInput(InputStream in){

System.out.println("Hiya!!!!");

message_in ="";

int ch;

StringBuffer sbuf =new StringBuffer();

try{

//while there is something to read

while ((ch = in.read()) != -1){

//if current character is a \r...

if (ch =='\r'){

//read next character

ch = in.read();

//if next character is a \n....

if (ch =='\n'){

//if buffer length is 0 then \r\n\r\n has been received

//so break out of while loop

if (sbuf.length() == 0)

break;

//if buffer length > 0 add buffer contents to vector

message_in += sbuf.toString();

//set buffer length to 0

sbuf.setLength(0);

}

}

//if character wasn't a \r then append character to the buffer

else sbuf.append((char)ch);

}

}

catch (Exception e){

System.out.println(e.getMessage());

}

}

}

Kind regards,

Chris

[12410 byte] By [lordflashearta] at [2007-10-2 9:34:59]
# 1

The problem lies with ProjectServer, wihin the while (listening) loop.

What the server does in this loop is:

1- accept a new socket connection

2- read message from client

3- return (same) message to client

And after that? Well it returns to step -1-.

The problem is that sthe step -1- is to accept new connection with new client(s) while your client is already connected to the server.

So in your while (listening) loop do:

1- accept a new socket connection from client

2- read message from client

3- return message to client

4- close connection

Since you will close the connection after each message roud trip on the server, you will have to do the same with the client.

So for the client, after each message inputed from the user, you'll have to:

1- create a new socket connection to server

2- write message to server

3- read message from server

4- close connection

And please in the HTTPClient class don't use recursion to send / receive messages, use a loop instead.

Regards

jfbrierea at 2007-7-16 23:41:15 > top of Java-index,Java Essentials,New To Java...
# 2

Thanks for that, I now see the problem and have sirted it and removed the recursive function.

As it is going to be an IM facility in the long term is there anyway I can uniquely identify each connection to the port? E.g. Each message sent from a client will have the username appended at the start of the message and possibly I could use this username to reference a connection. But if I was to have a second client running on the machine how would I ensure that my message is received by them and not everybody connected to the port?

Sorry if this is an inane question, very new to sockets.

Cheers again,

Chris

lordflashearta at 2007-7-16 23:41:15 > top of Java-index,Java Essentials,New To Java...