Java Forum / General / April 2007
Server and multiple sockets
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 MagazinesGet 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 ...
|
|
|