Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / April 2007

Tip: Looking for answers? Try searching our database.

Server and multiple sockets

Thread view: 
Chris - 22 Apr 2007 23:59 GMT
I'm a student, trying to write a server that can handle multiple
clients. It's closer to working than I was expecting but if I use
client 1, then client 2, client 1 then freezes. And then I can't close
the windows and have to stop the OS processes. The problem occurs with
this statement after port is defined:

     ServerSocket ss = new ServerSocket(port);

which causes this message:

    java.net.BindException: Address already in use: JVM_Bind

At that point no clients are running and nothing else has happened
with ports. I actually don't understand why the clients work at all,
since the socket doesn't seem to have been created successfully. After
the message above (and a trace), no other system messages appear
unless I try to close a window.

The following code includes comments using caps and ***, showing where
the trouble occurs. Any help greatly appreciated.

Chris
________________________________

package com.abc.server;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;

public class Server extends JPanel implements Runnable {
   private static JTextArea serverLog;
   private static int port;
   private static Socket soc;
   private static ObjectOutputStream oos;
   private static ObjectInputStream ois;
   private Thread internalThread;
   private static PrintStream out;

   public static void main(String[] args) {
       JFrame f = new JFrame("Server");
       f.setSize(600, 350);
       f.setDefaultCloseOperation(f.EXIT_ON_CLOSE);
       f.setVisible(true);
       serverLog = new JTextArea();
       f.add(serverLog);

       out = new PrintStream(new TextAreaOutputStream(serverLog));
       System.setOut(out);
       System.setErr(out);

       f.addWindowListener(new WindowAdapter() {
           public void windowClosing(WindowEvent e) {
               try {
                   ois.close();
                   oos.flush();
                   oos.close();
                   soc.close();
               } catch ( IOException ioe ) {
                   System.out.println(ioe + "\n");
                   ioe.printStackTrace();
               }
               System.exit(0);
           }
       });
       port = 2001;
       Server server = new Server();
       System.out.println("Leaving main.");
   }

   public Server() {
       internalThread = new Thread(this);
       internalThread.start();
   }

   public void run() {
       System.out.println("Server ready.");

           int i = 1;
           System.out.println("Start  of ");
           try {
           System.out.println("Start of connecting section. i = " +
i);
// *** EXECUTES CORRECTLY TO HERE
               ServerSocket ss = new ServerSocket(port);
// *** MESSAGE ISSUED HERE BUT SOCKET PARTIALLY WORKS
               for ( ;; ) {
                   Socket sock = ss.accept();
                   System.out.println("Got connection #" + i);
                   ClientService cs = new ClientService(sock, i,
out);
                   i++ ;
               }
           } catch ( IOException ioe ) {
               System.out.println(ioe + "\n");
               ioe.printStackTrace();
           }
// *** FOLLOWING PRINTS CORRECTLY BUT NO OTHER MESSAGES
       System.out.println("Connection established.");
   }
}

class ClientService implements Runnable {
   private static ObjectOutputStream oos;
   private static ObjectInputStream ois;
   private Thread internalThread;
   private Socket soc;
   private int counter;

   public ClientService(Socket s, int ctr, PrintStream outTxtArea) {
       soc = s;
       counter = ctr;
       PrintStream out = outTxtArea;
       System.setOut(out);
       System.setErr(out);
       internalThread = new Thread(this);
       internalThread.start();
       internalThread.interrupt();
   }

   public void run() {
       System.out.println("Thread for client #" + counter);
       try {
           final InputStream is = soc.getInputStream();
           oos = new ObjectOutputStream(soc.getOutputStream());
           ois = new ObjectInputStream(is);
           boolean done = false;
           while ( !done ) {
               String strFrmClnt = (String) ois.readObject();
               String strToClnt = strFrmClnt.length() + " - " +
strFrmClnt;
               if ( strFrmClnt == null ) {
                   done = true;
               } else {
                   oos.writeObject(strToClnt);
               }
           }
           ois.close();
           oos.flush();
           oos.close();
           soc.close();
       } catch ( ClassNotFoundException cnfe ) {
           System.out.println(cnfe + "\n");
           cnfe.printStackTrace();
       } catch ( IOException ioe ) {
           System.out.println(ioe + "\n");
           ioe.printStackTrace();
       }
   }
}
SadRed - 23 Apr 2007 00:14 GMT
> I'm a student, trying to write a server that can handle multiple
> clients. It's closer to working than I was expecting but if I use
[quoted text clipped - 150 lines]
>
> }

> if I use
> client 1, then client 2
You are re-creating the same server socket each time
new client is created. Stop it and use one single server
socket for accepting multiple clients. Server does not
need to have run() method because one single Main
thread is enough for the server to run. Dispatch a
client handler thread for each accept()ed client.
Chris - 23 Apr 2007 01:41 GMT
> > I'm a student, trying to write a server that can handle multiple
> > clients. It's closer to working than I was expecting but if I use
[quoted text clipped - 159 lines]
> thread is enough for the server to run. Dispatch a
> client handler thread for each accept()ed client.

What I thought I had was just one server, which would create multiple
ClientService threads, so I thought the ServerSocket was created only
once. Can you say why the Server itself would be multiple? I should
have mentioned part of the assignment was for the server to be in a
self-running thread; that's why I have the run() method. Is there a
different way to use the method?

Anyway, I tried putting the server socket assignment in its own try-
catch but the result is similar. After the try-catch, the ServerSocket
is still null.

       port = 2001;
       ServerSocket ss = null;
       try {
           ss = new ServerSocket(port);     \\ *** This fails
       } catch ( IOException ioes ) {
           System.out.println(ioes + "\n");
           ioes.printStackTrace();
       }

       int i = 1;
       try {
           System.out.println("Start of socket defn.");
           for ( ;; ) {
               Socket sock = ss.accept();
               System.out.println("Got connection #" + i);
               ClientService cs = new ClientService(sock, i, out);
               i++ ;
           }
       } catch ( IOException ioe ) {
           System.out.println(ioe + "\n");
           ioe.printStackTrace();
       }
Esmond Pitt - 23 Apr 2007 03:33 GMT
>>    public void run() {
>>        System.out.println("Server ready.");
[quoted text clipped - 9 lines]
> You are re-creating the same server socket each time
> new client is created.

Absolute rubbish. He isn't.

Chris, your code is mostly fine except that you should always close
output streams of a socket before the input, and in fact once you've
done that closing the input stream or the socket is redundant. I also
don't know why you're starting the client thread and then immediately
interrupting it - don't do that.

Your problem is coming when restarting the server. Use new
ServerSocket(), then call serverSocket.setReuseAddress(), then
serverSocket.bind() to get around this.
Chris - 23 Apr 2007 03:56 GMT
On Apr 22, 9:33 pm, Esmond Pitt <esmond.p...@nospam.bigpond.com>
wrote:

> >>    public void run() {
> >>        System.out.println("Server ready.");
[quoted text clipped - 21 lines]
> ServerSocket(), then call serverSocket.setReuseAddress(), then
> serverSocket.bind() to get around this.

Does this apply even when I've just started the program? Because I get
an error on the first time. Also, since my  "new ServerSocket"
statement is what causes the error, your other calls wouldn't affect
it if they came after it. One more question: I don't understand the
argument type for bind() -- it won't take the port number I'm using.
Thanks for your help.
Knute Johnson - 23 Apr 2007 06:22 GMT
> On Apr 22, 9:33 pm, Esmond Pitt <esmond.p...@nospam.bigpond.com>
> wrote:
[quoted text clipped - 27 lines]
> argument type for bind() -- it won't take the port number I'm using.
> Thanks for your help.

What port are you using?  Does some other program have that port
listening?  Try netstat -a before your run your program to see what's
going on.

Signature

Knute Johnson
email s/nospam/knute/

Chris - 23 Apr 2007 04:21 GMT
On Apr 22, 9:33 pm, Esmond Pitt <esmond.p...@nospam.bigpond.com>
wrote:

> >>    public void run() {
> >>        System.out.println("Server ready.");
[quoted text clipped - 21 lines]
> ServerSocket(), then call serverSocket.setReuseAddress(), then
> serverSocket.bind() to get around this.

I tried to follow your suggestions, and I at least got rid of the bind
error, but I'm getting a NullPointerException. With the other code
pretty much the same (but declaring the ServerSocket at the top), the
problematic statement now has three new statements before it. Eclipse
accepts them, but the result still isn't right.

               ss.setReuseAddress(true);
               SocketAddress socAdr=ss.getLocalSocketAddress();
               ss.bind(socAdr);
               ss = new ServerSocket(port);
Esmond Pitt - 23 Apr 2007 04:47 GMT
>                 ss.setReuseAddress(true);
>                 SocketAddress socAdr=ss.getLocalSocketAddress();
>                 ss.bind(socAdr);
>                 ss = new ServerSocket(port);

Delete the last 3 lines and replace with

        ss.bind(new InetSocketAddress(port));

If you get the BindException the first time you run it after a reboot,
someone else is already using the port, so you'll just have to use
another one.
Knute Johnson - 23 Apr 2007 06:21 GMT
> Chris, your code is mostly fine except that you should always close
> output streams of a socket before the input, and in fact once you've
> done that closing the input stream or the socket is redundant. I also
> don't know why you're starting the client thread and then immediately
> interrupting it - don't do that.

Actually I've found that you are better off closing the socket and
letting that close the streams.  On occasion closing the streams can
hang the socket up.  Less code too.

Signature

Knute Johnson
email s/nospam/knute/

Esmond Pitt - 23 Apr 2007 09:11 GMT
> Actually I've found that you are better off closing the socket and
> letting that close the streams.  On occasion closing the streams can
> hang the socket up.  Less code too.

But less data, too. The output stream doesn't get a chance to flush so
you will lose data. That's the only reason it can block (if the reader
is a way behind), but then of course it *should* block. Unless you like
truncated transmissions.
Knute Johnson - 23 Apr 2007 17:25 GMT
>> Actually I've found that you are better off closing the socket and
>> letting that close the streams.  On occasion closing the streams can
[quoted text clipped - 4 lines]
> is a way behind), but then of course it *should* block. Unless you like
> truncated transmissions.

If you are not done reading why would you be closing the streams?

There is some sort of bug/feature/whatever under Winblows if the socket
on the server end throws an exception caused by the other end closing,
and you then attempt to close the streams on the server it can hang.  It
shouldn't but it does occasionally.  If you just close the socket that
doesn't happen.

Signature

Knute Johnson
email s/nospam/knute/

Esmond Pitt - 24 Apr 2007 08:05 GMT
> If you are not done reading why would you be closing the streams?

Maybe I didn't make myself clear. If you try to close a buffered stream
and the *other* end is far enough behind in its reading, the flush()
implied by the close() will block, and this is surely the desired action.

> There is some sort of bug/feature/whatever under Winblows if the socket
> on the server end throws an exception caused by the other end closing,
> and you then attempt to close the streams on the server it can hang.  It
> shouldn't but it does occasionally.  If you just close the socket that
> doesn't happen.

Never seen or heard of it myself, but if you close in response to an
exception (other than EOFException) you should of course take the
shortest way home, which is certainly just to close the socket.
Knute Johnson - 24 Apr 2007 19:06 GMT
>> If you are not done reading why would you be closing the streams?
>
> Maybe I didn't make myself clear. If you try to close a buffered stream
> and the *other* end is far enough behind in its reading, the flush()
> implied by the close() will block, and this is surely the desired action.

I'm with you there.

>> There is some sort of bug/feature/whatever under Winblows if the
>> socket on the server end throws an exception caused by the other end
[quoted text clipped - 5 lines]
> exception (other than EOFException) you should of course take the
> shortest way home, which is certainly just to close the socket.

That's what I think.

Signature

Knute Johnson
email s/nospam/knute/

Knute Johnson - 23 Apr 2007 00:52 GMT
> I'm a student, trying to write a server that can handle multiple
> clients. It's closer to working than I was expecting but if I use
[quoted text clipped - 148 lines]
>     }
> }

It looks to me like the server part should be working.  The
BindException is caused by trying to open two sockets (server or
otherwise) on the same port.  Could it be that you have two servers running?

There are a couple of odd things, one is why do you interrupt your
internalThread right after you create it in you client?  I can't see any
reason for that but since you don't have any code that will throw an
InterruptedException in your client it really shouldn't cause you any
problem.  Normally one wraps the server creation code in a permanent
loop in case it throws an exception.  If you throw an exception in your
server it will stop.

I would rename the client code to something like server task as that is
closer to its function.  The client is the code that talks to this code.

You are declaring ObjectInput/OutputStreams in both classes.  You only
really need them in the task part of the code.

I just had a thought, are you trying to create two of these objects and
connecting them together?

Signature

Knute Johnson
email s/nospam/knute/

Chris - 23 Apr 2007 23:15 GMT
> I'm a student, trying to write a server that can handle multiple
> clients. It's closer to working than I was expecting but if I use
[quoted text clipped - 152 lines]
>
> - Show quoted text -

I received a number of responses with interesting suggestions but
someone in my company found the problem-- embarrassingly simple as
these things sometimes are. My input and output streams in the
ClientService class were declared static. So the conflict between the
client instances had to happen. (I guess I was sticking "static" on
things because Eclipse kept bugging me about variables.) Thanks to all
who looked over my code.
SadRed - 24 Apr 2007 00:09 GMT
> > I'm a student, trying to write a server that can handle multiple
> > clients. It's closer to working than I was expecting but if I use
[quoted text clipped - 160 lines]
> things because Eclipse kept bugging me about variables.) Thanks to all
> who looked over my code.

Awfull. Your Server class also has a few static fields. We had
taken for granted that there can't be such code in c/s program.
But there were!


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.