Socket problems

J

JS

Hi everyone. I'm trying to write a 20 client chat server which is not web
based (the only reason I say that is because all the examples I have found
so far are applets, JSP etc)
In the client side I'm trying to listen for input from the user and for
messages from the server at the same time. Well almost, there is a SoTimeout
of 50milliseconds which swaps between listening from the System.in and the
server.

A similar story on the server side but this calls methods for listening for
new clients connecting and messages from the existing clients. The server
has this code:

public void receive()
{
System.out.println("Waiting for new clients");
try
{
socket = serverSocket.accept();
socket.setSoTimeout(50);
BufferedReader inFromClient = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
String clientSentence = inFromClient.readLine();
System.out.println("someone said "+clientSentence);
process(clientSentence, socket);
}
catch(IOException e)
{
System.out.println(e);
System.out.println("A new client could not be found");
listenFromClients();
}
listenFromClients();
}

public void listenFromClients()
{
System.out.println("Waiting for a known client to speak");
for(int i = 0; i < clients.size(); i++)
{
Tuple t = (Tuple)clients.get(i);
socket = t.getSocket();
try
{
socket.setSoTimeout(50);
BufferedReader in = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
String clientSentence = in.readLine();
System.out.println(t.getName()+ " said "+clientSentence);
process(clientSentence, socket);
}
catch(IOException e)
{
System.out.println(e);
System.out.println("Known client "+i+" timed out");
continue;
}
}
receive();
}

and the client has this:

public void start()
{
String first = connect();
if(first != null)
{
send(first);
}
while(true)
{
receive();
getClientInput();
}

}

public String connect()
{
try
{
String toServer = InetAddress.getLocalHost().getHostName();
return ("connect: "+toServer+" "+name+"\n");
}
catch(IOException e)
{
System.out.println(e);
System.out.println("The host name of your computer could not be
found");
System.out.println("The system will now exit");
System.exit(3);
}
return null;
}

public void send(String message)
{
try
{
DataOutputStream outToServer = new
DataOutputStream(socket.getOutputStream());
outToServer.writeBytes(message);
receive();
}
catch(IOException e)
{
System.out.println(e);
System.out.println("The message could not be sent");
}
}

public void receive()
{
try
{
BufferedReader inFromServer = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
String sentence = inFromServer.readLine();
process(sentence);
}
catch(IOException e)
{
System.out.println(e);
System.out.println("The message could not be received hello");
//getClientInput();
}

}

public void getClientInput()
{
try
{
BufferedReader inFromClient = new BufferedReader(new
InputStreamReader(System.in));
System.out.println("Enter some text....");
String in = inFromClient.readLine();
send("message: "+name+": "+in);
}
catch(IOException e)
{
System.out.println(e);
System.out.println("That message could not be read from you");
//receive();
}
}

The socket keeps timing out and the errors are caught but neither class
seems to carry on listening with the other method. I would use threads but
Sockets and networks are new to me let alone threads as well, although it
might be possible with some collaboration.
There are a lot of System.out.println() statments here purely so we could
see what was happening. Now in theory the server should print out a new line
each time it swaps methods but it doesnt.
Any help is greatly appreciated and if you need any further details then
feel free to ask.
Thanks a lot everyone
JS
 
O

Oliver Wong

JS said:
Hi everyone. I'm trying to write a 20 client chat server which is not web
based (the only reason I say that is because all the examples I have found
so far are applets, JSP etc)
In the client side I'm trying to listen for input from the user and for
messages from the server at the same time. Well almost, there is a
SoTimeout
of 50milliseconds which swaps between listening from the System.in and the
server.

A similar story on the server side but this calls methods for listening
for
new clients connecting and messages from the existing clients. The server
has this code:

public void receive()
{
System.out.println("Waiting for new clients");
try
{
socket = serverSocket.accept();
socket.setSoTimeout(50);
BufferedReader inFromClient = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
String clientSentence = inFromClient.readLine();
System.out.println("someone said "+clientSentence);
process(clientSentence, socket);
}
catch(IOException e)
{
System.out.println(e);
System.out.println("A new client could not be found");
listenFromClients();
}
listenFromClients();
}

public void listenFromClients()
{
System.out.println("Waiting for a known client to speak");
for(int i = 0; i < clients.size(); i++)
{
Tuple t = (Tuple)clients.get(i);
socket = t.getSocket();
try
{
socket.setSoTimeout(50);
BufferedReader in = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
String clientSentence = in.readLine();
System.out.println(t.getName()+ " said "+clientSentence);
process(clientSentence, socket);
}
catch(IOException e)
{
System.out.println(e);
System.out.println("Known client "+i+" timed out");
continue;
}
}
receive();
}

[snip]

It seems to me you have an infinite recursion with listenFromClients()
calling receive() and vice versa. This will eventually use up all the stack
space causing your server to run out of memory.

Instead, you probably want something like this:

<code>
while (true) {
receive();
listenFromClients();
}
</code>

and not have either method call the other one directly.

- Oliver
 
K

Knute Johnson

JS said:
Hi everyone. I'm trying to write a 20 client chat server which is not web
based (the only reason I say that is because all the examples I have found
so far are applets, JSP etc)
In the client side I'm trying to listen for input from the user and for
messages from the server at the same time. Well almost, there is a SoTimeout
of 50milliseconds which swaps between listening from the System.in and the
server.

A similar story on the server side but this calls methods for listening for
new clients connecting and messages from the existing clients. The server
has this code:

public void receive()
{
System.out.println("Waiting for new clients");
try
{
socket = serverSocket.accept();
socket.setSoTimeout(50);
BufferedReader inFromClient = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
String clientSentence = inFromClient.readLine();
System.out.println("someone said "+clientSentence);
process(clientSentence, socket);
}
catch(IOException e)
{
System.out.println(e);
System.out.println("A new client could not be found");
listenFromClients();
}
listenFromClients();
}

public void listenFromClients()
{
System.out.println("Waiting for a known client to speak");
for(int i = 0; i < clients.size(); i++)
{
Tuple t = (Tuple)clients.get(i);
socket = t.getSocket();
try
{
socket.setSoTimeout(50);
BufferedReader in = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
String clientSentence = in.readLine();
System.out.println(t.getName()+ " said "+clientSentence);
process(clientSentence, socket);
}
catch(IOException e)
{
System.out.println(e);
System.out.println("Known client "+i+" timed out");
continue;
}
}
receive();
}

and the client has this:

public void start()
{
String first = connect();
if(first != null)
{
send(first);
}
while(true)
{
receive();
getClientInput();
}

}

public String connect()
{
try
{
String toServer = InetAddress.getLocalHost().getHostName();
return ("connect: "+toServer+" "+name+"\n");
}
catch(IOException e)
{
System.out.println(e);
System.out.println("The host name of your computer could not be
found");
System.out.println("The system will now exit");
System.exit(3);
}
return null;
}

public void send(String message)
{
try
{
DataOutputStream outToServer = new
DataOutputStream(socket.getOutputStream());
outToServer.writeBytes(message);
receive();
}
catch(IOException e)
{
System.out.println(e);
System.out.println("The message could not be sent");
}
}

public void receive()
{
try
{
BufferedReader inFromServer = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
String sentence = inFromServer.readLine();
process(sentence);
}
catch(IOException e)
{
System.out.println(e);
System.out.println("The message could not be received hello");
//getClientInput();
}

}

public void getClientInput()
{
try
{
BufferedReader inFromClient = new BufferedReader(new
InputStreamReader(System.in));
System.out.println("Enter some text....");
String in = inFromClient.readLine();
send("message: "+name+": "+in);
}
catch(IOException e)
{
System.out.println(e);
System.out.println("That message could not be read from you");
//receive();
}
}

The socket keeps timing out and the errors are caught but neither class
seems to carry on listening with the other method. I would use threads but
Sockets and networks are new to me let alone threads as well, although it
might be possible with some collaboration.
There are a lot of System.out.println() statments here purely so we could
see what was happening. Now in theory the server should print out a new line
each time it swaps methods but it doesnt.
Any help is greatly appreciated and if you need any further details then
feel free to ask.
Thanks a lot everyone
JS

JS:

You are going to need to use threads. They really aren't as complicated
as they seem if you keep your logic simple. With what you have your
sockets will time out and close. No communications will happen then.

The server end needs to do two basic things, handle incoming connections
and create threaded tasks that will send data between each other and to
and from the clients.

This is the basic logic for a simple connection handler:

ServerSocket ss = new ServerSocket(SOMEPORT);
while (true) {
Socket s = ss.accept(); // wait for connection
// create a new communicator task and pass it the socket
CommTask ct = new CommTask(s);
// add reference to the task to a vector
commTaskVector.add(ct);
}

The communicator task then needs to receive data from its client and
pass it to the other communicator tasks and receive data from the other
communcator tasks and pass it to its client.

class CommTask implements Runnable {
OutputStream os;
InputStream is;

public CommTask(Socket s) {
is = s.getInputStream();
os = s.getOutputStream();

new Thread(this).start(); // start thread - it executes run()
}

public void run() {
// read from input stream
// iterate through commTaskVector and write data to
// other tasks via their write method
}

public void write(bye[] buf) {
// write data from other tasks to output stream
}

This is just an outline. You will need to handle the IOExceptions,
timeouts, and cleanup when clients leave. The write methods will have
to be synchronized as will access to the Vector that holds the list of
communicator tasks.

A chat server is really a pretty compilicated thing when you get right
down to it. I have a simple UDP transceiver that I wrote to communicate
between two points that I would be happy to give you the source code
for. It might be fun to play with and would be a start to see how
multithreaded code works.
 
J

JS

Hi Knute,
Would it be possible to email that code you mentioned to me at
(e-mail address removed)

Hi Oliver, we did try using a while(true) loop and it seemed to have less
effect than the other method

My group has tried loads of things and we really are getting stuck for
ideas. Any help is appreciated.
Thanks everyone and any more ideas are always welcome
JS

Knute Johnson said:
JS said:
Hi everyone. I'm trying to write a 20 client chat server which is not web
based (the only reason I say that is because all the examples I have found
so far are applets, JSP etc)
In the client side I'm trying to listen for input from the user and for
messages from the server at the same time. Well almost, there is a SoTimeout
of 50milliseconds which swaps between listening from the System.in and the
server.

A similar story on the server side but this calls methods for listening for
new clients connecting and messages from the existing clients. The server
has this code:

public void receive()
{
System.out.println("Waiting for new clients");
try
{
socket = serverSocket.accept();
socket.setSoTimeout(50);
BufferedReader inFromClient = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
String clientSentence = inFromClient.readLine();
System.out.println("someone said "+clientSentence);
process(clientSentence, socket);
}
catch(IOException e)
{
System.out.println(e);
System.out.println("A new client could not be found");
listenFromClients();
}
listenFromClients();
}

public void listenFromClients()
{
System.out.println("Waiting for a known client to speak");
for(int i = 0; i < clients.size(); i++)
{
Tuple t = (Tuple)clients.get(i);
socket = t.getSocket();
try
{
socket.setSoTimeout(50);
BufferedReader in = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
String clientSentence = in.readLine();
System.out.println(t.getName()+ " said "+clientSentence);
process(clientSentence, socket);
}
catch(IOException e)
{
System.out.println(e);
System.out.println("Known client "+i+" timed out");
continue;
}
}
receive();
}

and the client has this:

public void start()
{
String first = connect();
if(first != null)
{
send(first);
}
while(true)
{
receive();
getClientInput();
}

}

public String connect()
{
try
{
String toServer = InetAddress.getLocalHost().getHostName();
return ("connect: "+toServer+" "+name+"\n");
}
catch(IOException e)
{
System.out.println(e);
System.out.println("The host name of your computer could not be
found");
System.out.println("The system will now exit");
System.exit(3);
}
return null;
}

public void send(String message)
{
try
{
DataOutputStream outToServer = new
DataOutputStream(socket.getOutputStream());
outToServer.writeBytes(message);
receive();
}
catch(IOException e)
{
System.out.println(e);
System.out.println("The message could not be sent");
}
}

public void receive()
{
try
{
BufferedReader inFromServer = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
String sentence = inFromServer.readLine();
process(sentence);
}
catch(IOException e)
{
System.out.println(e);
System.out.println("The message could not be received hello");
//getClientInput();
}

}

public void getClientInput()
{
try
{
BufferedReader inFromClient = new BufferedReader(new
InputStreamReader(System.in));
System.out.println("Enter some text....");
String in = inFromClient.readLine();
send("message: "+name+": "+in);
}
catch(IOException e)
{
System.out.println(e);
System.out.println("That message could not be read from you");
//receive();
}
}

The socket keeps timing out and the errors are caught but neither class
seems to carry on listening with the other method. I would use threads but
Sockets and networks are new to me let alone threads as well, although it
might be possible with some collaboration.
There are a lot of System.out.println() statments here purely so we could
see what was happening. Now in theory the server should print out a new line
each time it swaps methods but it doesnt.
Any help is greatly appreciated and if you need any further details then
feel free to ask.
Thanks a lot everyone
JS

JS:

You are going to need to use threads. They really aren't as complicated
as they seem if you keep your logic simple. With what you have your
sockets will time out and close. No communications will happen then.

The server end needs to do two basic things, handle incoming connections
and create threaded tasks that will send data between each other and to
and from the clients.

This is the basic logic for a simple connection handler:

ServerSocket ss = new ServerSocket(SOMEPORT);
while (true) {
Socket s = ss.accept(); // wait for connection
// create a new communicator task and pass it the socket
CommTask ct = new CommTask(s);
// add reference to the task to a vector
commTaskVector.add(ct);
}

The communicator task then needs to receive data from its client and
pass it to the other communicator tasks and receive data from the other
communcator tasks and pass it to its client.

class CommTask implements Runnable {
OutputStream os;
InputStream is;

public CommTask(Socket s) {
is = s.getInputStream();
os = s.getOutputStream();

new Thread(this).start(); // start thread - it executes run()
}

public void run() {
// read from input stream
// iterate through commTaskVector and write data to
// other tasks via their write method
}

public void write(bye[] buf) {
// write data from other tasks to output stream
}

This is just an outline. You will need to handle the IOExceptions,
timeouts, and cleanup when clients leave. The write methods will have
to be synchronized as will access to the Vector that holds the list of
communicator tasks.

A chat server is really a pretty compilicated thing when you get right
down to it. I have a simple UDP transceiver that I wrote to communicate
between two points that I would be happy to give you the source code
for. It might be fun to play with and would be a start to see how
multithreaded code works.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,981
Messages
2,570,187
Members
46,731
Latest member
MarcyGipso

Latest Threads

Top