package Ninja;




import java.io.*;
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

import java.net.*;

public class NinjaServer implements Runnable {
	
	   public final static int NULL = 0;
	   public final static int DISCONNECTED = 1;
	   public final static int DISCONNECTING = 2;
	   public final static int BEGIN_CONNECT = 3;
	   public final static int CONNECTED = 4;

	   public final static String statusMessages[] = {
		      " Can't Connect!!! Don't Try Again!", " Disconnected",
		      " Disconnecting...", " Connecting... Please Wait", " Connected"
		   };
		   public final static NinjaServer NinjaObj = new NinjaServer();
		   public final static String END_CHAT_SESSION =
		      new Character((char)0).toString(); 
		   
		   public static String hostIP = "localhost";
		   public static int port = 1337;
		   public static int connectionStatus = DISCONNECTED;
		   public static boolean isHost = true;
		   public static String statusString = statusMessages[connectionStatus];
		   public static StringBuffer toAppend = new StringBuffer("");
		   public static StringBuffer toSend = new StringBuffer("");
		   
		   
		   // Various GUI components and info
		   public static JFrame mainFrame = null;
		   public static JTextArea chatText = null;
		   public static JTextField chatLine = null;
		   public static JPanel statusBar = null;
		   public static JLabel statusField = null;
		   public static JTextField statusColor = null;
		   public static JTextField ipField = null;
		   public static JTextField portField = null;
		   public static JRadioButton hostOption = null;
		   public static JRadioButton guestOption = null;
		   public static JRadioButton NinjaOption = null;
		   public static JButton helpButton = null;
		   public static JButton connectButton = null;
		   public static JButton disconnectButton = null;
		   
		   public static ServerSocket hostServer = null;
		   public static Socket socket = null;
		   public static BufferedReader in = null;
		   public static PrintWriter out = null;
		   
		   private static JPanel initOptionsPane() {
			      JPanel pane = null;
			      ActionAdapter buttonListener = null;
			      
			      JPanel optionsPane = new JPanel(new GridLayout(4, 1));
			      
			      pane = new JPanel(new FlowLayout(FlowLayout.RIGHT));
			      pane.add(new JLabel("Computer Name:"));
			      ipField = new JTextField(10); ipField.setText(hostIP);
			      ipField.setEnabled(false);
			      ipField.addFocusListener(new FocusAdapter() {
			            public void focusLost(FocusEvent e) {
			               ipField.selectAll();
			               // Should be editable only when disconnected
			               if (connectionStatus != DISCONNECTED) {
			                  changeStatusNTS(NULL, true);
			               }
			               else {
			                  hostIP = ipField.getText();
			               }
			            }
			         });
			      
			      pane.add(ipField);
			      optionsPane.add(pane);

			      // Port input
			      pane = new JPanel(new FlowLayout(FlowLayout.RIGHT));
			      pane.add(new JLabel("Port Number:"));
			      portField = new JTextField(10); portField.setEditable(true);
			      portField.setText((new Integer(port)).toString());
			      portField.addFocusListener(new FocusAdapter() {
			            public void focusLost(FocusEvent e) {
			               // should be editable only when disconnected
			               if (connectionStatus != DISCONNECTED) {
			                  changeStatusNTS(NULL, true);
			               }
			               else {
			                  int temp;
			                  try {
			                     temp = Integer.parseInt(portField.getText());
			                     port = temp;
			                  }
			                  
			                  catch (NumberFormatException nfe) {
			                     portField.setText((new Integer(port)).toString());
			                     mainFrame.repaint();
			                  }
			               }
			            }
			         });
			      pane.add(portField);
			      optionsPane.add(pane);
			      
			      buttonListener = new ActionAdapter() {
			            public void actionPerformed(ActionEvent e) {
			               if (connectionStatus != DISCONNECTED) {
			                  changeStatusNTS(NULL, true);
			               }
			               
			               else {
			                  isHost = e.getActionCommand().equals("host");

			                  // Cannot supply host IP if host option is chosen
			                  if (isHost) {
			                     ipField.setEnabled(false);
			                     ipField.setText("localhost");
			                     hostIP = "localhost";
			                  }
			                  else {
			                     ipField.setEnabled(true);
			                  }
			               }
			            }
			         };
			      ButtonGroup bg = new ButtonGroup();
			      hostOption = new JRadioButton("Host", true);
			      hostOption.setMnemonic(KeyEvent.VK_H);
			      hostOption.setActionCommand("host");
			      hostOption.addActionListener(buttonListener);
			      guestOption = new JRadioButton("Guest", false);
			      guestOption.setMnemonic(KeyEvent.VK_G);
			      guestOption.setActionCommand("guest");
			      guestOption.addActionListener(buttonListener);
			      
			      NinjaOption = new JRadioButton ("Ninja", false);
			      NinjaOption.setMnemonic(KeyEvent.VK_N);
			      NinjaOption.setActionCommand("Ninja");
			      NinjaOption.addActionListener(buttonListener);
			      
			      bg.add(hostOption);
			      bg.add(guestOption);
			      bg.add(NinjaOption);
			      pane = new JPanel(new GridLayout(1, 2));
			      pane.add(hostOption);
			      pane.add(guestOption);
			      pane.add(NinjaOption);
			      optionsPane.add(pane);
			      
			      JPanel buttonPane = new JPanel(new GridLayout(1, 2));
			      buttonListener = new ActionAdapter() {
			            public void actionPerformed(ActionEvent e) {
			               // Request a connection initiation
			               if (e.getActionCommand().equals("connect")) {
			                  changeStatusNTS(BEGIN_CONNECT, true);
			               }
			               // Disconnect
			               else {
			                  changeStatusNTS(DISCONNECTING, true);
			               }
			            }
			         };
			      connectButton = new JButton("Connect");
			      connectButton.setMnemonic(KeyEvent.VK_C);
			      connectButton.setActionCommand("connect");
			      connectButton.addActionListener(buttonListener);
			      connectButton.setEnabled(true);
			      disconnectButton = new JButton("Disconnect");
			      disconnectButton.setMnemonic(KeyEvent.VK_D);
			      disconnectButton.setActionCommand("disconnect");
			      disconnectButton.addActionListener(buttonListener);
			      disconnectButton.setEnabled(false);
			      buttonPane.add(connectButton);
			      buttonPane.add(disconnectButton);
			      optionsPane.add(buttonPane);

			      return optionsPane;
			   }
		   // Initialize all the GUI components and display the frame
		   private static void initGUI() {
		      // Set up the status bar
		      statusField = new JLabel();
		      statusField.setText(statusMessages[DISCONNECTED]);
		      statusColor = new JTextField(1);
		      statusColor.setBackground(Color.red);
		      statusColor.setEditable(false);
		      statusBar = new JPanel(new BorderLayout());
		      statusBar.add(statusColor, BorderLayout.EAST);
		      statusBar.add(statusField, BorderLayout.CENTER);

		      // Set up the options pane
		      JPanel optionsPane = initOptionsPane();

		      // Set up the chat pane
		      JPanel chatPane = new JPanel(new BorderLayout());
		      chatText = new JTextArea(15, 30);
		      chatText.setLineWrap(true);
		      chatText.setEditable(false);
		      chatText.setForeground(Color.green);
		      JScrollPane chatTextPane = new JScrollPane(chatText,
		         JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
		         JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		      chatLine = new JTextField();
		      chatLine.setEnabled(false);
		      chatLine.addActionListener(new ActionAdapter() {
		            public void actionPerformed(ActionEvent e) {
		               String s = chatLine.getText();
		               if (!s.equals("")) {
		                  appendToChatBox("OUTGOING: " + s + "\n");
		                  chatLine.selectAll();

		                  // Send the string
		                  sendString(s);
		               }
		            }
		         });
		      chatPane.add(chatLine, BorderLayout.SOUTH);
		      chatPane.add(chatTextPane, BorderLayout.CENTER);
		      chatPane.setPreferredSize(new Dimension(200, 200));

		      // Set up the main pane
		      JPanel mainPane = new JPanel(new BorderLayout());
		      mainPane.add(statusBar, BorderLayout.SOUTH);
		      mainPane.add(optionsPane, BorderLayout.WEST);
		      mainPane.add(chatPane, BorderLayout.CENTER);

		      // Set up the main frame
		      mainFrame = new JFrame("Simple Instant Messenger (SIM)");
		      mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		      mainFrame.setContentPane(mainPane);
		      mainFrame.setSize(mainFrame.getPreferredSize());
		      mainFrame.setLocation(1, 1);
		      mainFrame.pack();
		      mainFrame.setVisible(true);
		   }

		   /////////////////////////////////////////////////////////////////

		   // The thread-safe way to change the GUI components while
		   // changing state
		   private static void changeStatusTS(int newConnectStatus, boolean noError) {
		      // Change state if valid state
		      if (newConnectStatus != NULL) {
		         connectionStatus = newConnectStatus;
		      }

		      // If there is no error, display the appropriate status message
		      if (noError) {
		         statusString = statusMessages[connectionStatus];
		      }
		      // Otherwise, display error message
		      else {
		         statusString = statusMessages[NULL];
		      }

		      // Call the run() routine (Runnable interface) on the
		      // error-handling and GUI-update thread
		      SwingUtilities.invokeLater(NinjaObj);
		   }

		   /////////////////////////////////////////////////////////////////

		   // The non-thread-safe way to change the GUI components while
		   // changing state
		   private static void changeStatusNTS(int newConnectStatus, boolean noError) {
		      // Change state if valid state
		      if (newConnectStatus != NULL) {
		         connectionStatus = newConnectStatus;
		      }

		      // If there is no error, display the appropriate status message
		      if (noError) {
		         statusString = statusMessages[connectionStatus];
		      }
		      // Otherwise, display error message
		      else {
		         statusString = statusMessages[NULL];
		      }

		      // Call the run() routine (Runnable interface) on the
		      // current thread
		      NinjaObj.run();
		   }

		   /////////////////////////////////////////////////////////////////

		   // Thread-safe way to append to the chat box
		   private static void appendToChatBox(String s) {
		      synchronized (toAppend) {
		         toAppend.append(s);
		      }
		   }

		   /////////////////////////////////////////////////////////////////

		   // Add text to send-buffer
		   private static void sendString(String s) {
		      synchronized (toSend) {
		         toSend.append(s + "\n");
		      }
		   }

		   /////////////////////////////////////////////////////////////////

		   // Cleanup for disconnect
		   private static void cleanUp() {
		      try {
		         if (hostServer != null) {
		            hostServer.close();
		            hostServer = null;
		         }
		      }
		      catch (IOException e) { hostServer = null; }

		      try {
		         if (socket != null) {
		            socket.close();
		            socket = null;
		         }
		      }
		      catch (IOException e) { socket = null; }

		      try {
		         if (in != null) {
		            in.close();
		            in = null;
		         }
		      }
		      catch (IOException e) { in = null; }

		      if (out != null) {
		         out.close();
		         out = null;
		      }
		   }

		   /////////////////////////////////////////////////////////////////

		   // Checks the current state and sets the enables/disables
		   // accordingly
		   public void run() {
		      switch (connectionStatus) {
		      case DISCONNECTED:
		         connectButton.setEnabled(true);
		         disconnectButton.setEnabled(false);
		         ipField.setEnabled(true);
		         portField.setEnabled(true);
		         hostOption.setEnabled(true);
		         guestOption.setEnabled(true);
		         NinjaOption.setEnabled(true);
		         chatLine.setText(""); chatLine.setEnabled(false);
		         statusColor.setBackground(Color.red);
		         break;

		      case DISCONNECTING:
		         connectButton.setEnabled(false);
		         disconnectButton.setEnabled(false);
		         ipField.setEnabled(false);
		         portField.setEnabled(false);
		         hostOption.setEnabled(false);
		         guestOption.setEnabled(false);
		         NinjaOption.setEnabled(false);
		         chatLine.setEnabled(false);
		         statusColor.setBackground(Color.yellow);
		         break;

		      case CONNECTED:
		         connectButton.setEnabled(false);
		         disconnectButton.setEnabled(true);
		         ipField.setEnabled(false);
		         portField.setEnabled(false);
		         hostOption.setEnabled(false);
		         guestOption.setEnabled(false);
		         NinjaOption.setEnabled(false);
		         chatLine.setEnabled(true);
		         statusColor.setBackground(Color.green);
		         break;

		      case BEGIN_CONNECT:
		         connectButton.setEnabled(false);
		         disconnectButton.setEnabled(false);
		         ipField.setEnabled(false);
		         portField.setEnabled(false);
		         hostOption.setEnabled(false);
		         guestOption.setEnabled(false);
		         NinjaOption.setEnabled(false);
		         chatLine.setEnabled(false);
		         chatLine.grabFocus();
		         statusColor.setBackground(Color.yellow);
		         break;
		      }

		      // Make sure that the button/text field states are consistent
		      // with the internal states
		      ipField.setText(hostIP);
		      portField.setText((new Integer(port)).toString());
		      hostOption.setSelected(isHost);
		      guestOption.setSelected(!isHost);
		      NinjaOption.setSelected(!isHost);
		      statusField.setText(statusString);
		      chatText.append(toAppend.toString());
		      toAppend.setLength(0);

		      mainFrame.repaint();
		   }
		   
		   

		   /////////////////////////////////////////////////////////////////

		   // The main procedure
		   public static void main(String args[]) throws IOException {
		      String s;

		      initGUI();

		      while (true) {
		         try { // Poll every ~10 ms
		            Thread.sleep(10);
		         }
		         catch (InterruptedException e) {}

		         switch (connectionStatus) {
		         case BEGIN_CONNECT:
		            try {
		               // Try to set up a server if host
		               if (isHost) {
		                  hostServer = new ServerSocket(port);
		                  socket = hostServer.accept();
		                  
		                  Thread t = new Thread();
						  t.start();
		               }

		               // If guest, try to connect to the server
		               else {
		                  socket = new Socket(hostIP, port);
		               }

		               in = new BufferedReader(new 
		                  InputStreamReader(socket.getInputStream()));
		               out = new PrintWriter(socket.getOutputStream(), true);
		               changeStatusTS(CONNECTED, true);
		            }
		            // If error, clean up and output an error message
		            catch (IOException e) {
		               cleanUp();
		               changeStatusTS(DISCONNECTED, false);
		            }
		            break;

		         case CONNECTED:
		            try {
		               // Send data
		               if (toSend.length() != 0) {
		                  out.print(toSend); out.flush();
		                  toSend.setLength(0);
		                  changeStatusTS(NULL, true);
		               }

		               // Receive data
		               if (in.ready()) {
		                  s = in.readLine();
		                  if ((s != null) &&  (s.length() != 0)) {
		                     // Check if it is the end of a trasmission
		                     if (s.equals(END_CHAT_SESSION)) {
		                        changeStatusTS(DISCONNECTING, true);
		                     }

		                     // Otherwise, receive what text
		                     else {
		                        appendToChatBox("INCOMING: " + s + "\n");
		                        changeStatusTS(NULL, true);
		                     }
		                  }
		               }
		            }
		            catch (IOException e) {
		               cleanUp();
		               changeStatusTS(DISCONNECTED, false);
		            }
		            break;

		         case DISCONNECTING:
		            // Tell other chatter to disconnect as well
		            out.print(END_CHAT_SESSION); out.flush();

		            // Clean up (close all streams/sockets)
		            cleanUp();
		            changeStatusTS(DISCONNECTED, true);
		            break;

		         default: break; // do nothing
		         }
		      }
		   }
		}

//////////////////////////////////////////////////////////////////		//

//		 Action adapter for easy event-listener coding
		class ActionAdapter implements ActionListener {
		   public void actionPerformed(ActionEvent e) {}
		}

//////////////////////////////////////////////////////////////////		//

I have two problems with this instant messenger at the current moment.

First : I still can't figure out how to get multiple clients to connect to the host. It says connected, but there is no actual Incoming and Outgoing messages.

Second : When I connect to the server as guest, once connected, it switches over to Ninja

Recommended Answers

All 18 Replies

^bump :)

Someone please help?

Okay, let me shorten this a little.

My goal is to make a multiclient Instant Messenger program. When executing, there are no errors, but it can only support host / client. I am not sure where to put and exactly what to put to make it a multi user program.

public static void main(String args[]) throws IOException {
		      String s;

		      initGUI();

		      while (true) {
		    	  
		    	 NinjaServer n = null;
		         try { // Poll every ~10 ms
		            Thread.sleep(10);
		         }
		         catch (InterruptedException e) {}

		         switch (connectionStatus) {
		         case BEGIN_CONNECT:
		            try {
		               // Try to set up a server if host
		               if (isHost) {
		                  hostServer = new ServerSocket(port);
		                  socket = hostServer.accept();
		                  
		                  Thread t = new Thread(n);
						  t.start();
						  
		               }

		               // If guest, try to connect to the server
		               else {
		                  socket = new Socket(hostIP, port);
		               }

		               in = new BufferedReader(new 
		                  InputStreamReader(socket.getInputStream()));
		               out = new PrintWriter(socket.getOutputStream(), true);
		               changeStatusTS(CONNECTED, true);
		            }
		            // If error, clean up and output an error message
		            catch (IOException e) {
		               cleanUp();
		               changeStatusTS(DISCONNECTED, false);
		            }
		            break;

		         case CONNECTED:
		            try {
		               // Send data
		               if (toSend.length() != 0) {
		                  out.print(toSend); out.flush();
		                  toSend.setLength(0);
		                  changeStatusTS(NULL, true);
		               }

		               // Receive data
		               if (in.ready()) {
		                  s = in.readLine();
		                  if ((s != null) &&  (s.length() != 0)) {
		                     // Check if it is the end of a trasmission
		                     if (s.equals(END_CHAT_SESSION)) {
		                        changeStatusTS(DISCONNECTING, true);
		                     }

		                     // Otherwise, receive what text
		                     else {
		                        appendToChatBox("INCOMING: " + s + "\n");
		                        changeStatusTS(NULL, true);
		                     }
		                  }
		               }
		            }
		            catch (IOException e) {
		               cleanUp();
		               changeStatusTS(DISCONNECTED, false);
		            }
		            break;

		         case DISCONNECTING:
		            // Tell other chatter to disconnect as well
		            out.print(END_CHAT_SESSION); out.flush();

		            // Clean up (close all streams/sockets)
		            cleanUp();
		            changeStatusTS(DISCONNECTED, true);
		            break;

		         default: break; // do nothing
		         }
		      }
		   }
		}

No one has any input or advice ?

:(

When executing, there are no errors, but it can only support host / client.

hmm , I have traced your code , this like a Serial port RS-232 communication .

I think you have to connect to the server to enable the multi user chat , like the IRC chat ! I think you have to change the coce

// Try to set up a server if host
if (isHost) {
         hostServer = new ServerSocket(port);
         socket = hostServer.accept();
         Thread t = new Thread(n);
         t.start();
}
// If guest, try to connect to the server
else {
        socket = new Socket(hostIP, port);

}

something should be change here ....


just put a watch point on the variable socket and see what is the really value on it on the runtime . after executing the above me quoted code .

hmm , nice chat program that you copied and pasted from ,


public static String hostIP = "localhost";
and localhost means your computer , then you are using the server as your computer
if you are start chat with him . Look at the quoted text in my previous post . If your friend is starting chat with you then his computer is working as a server and your computer just accept that connection .

So if you want's to chat more than 2 users , then you have to make a intermeadiate server and make that server to work as a router to forward your msg to the friend .

I dont get what you are trying to say. I do connect to the server, but that doesn't enable multiple clients.

What is a watch point? Sorry , I just started recently and don't know all the terms yet.

What I don't get is why it won't just allow more clients, because I am starting new threads and everything.

This guy , the only guy that attempted helping, responded 32 minutes ago. Now he is banned.

// Try to set up a server if host
if (isHost) {
         hostServer = new ServerSocket(port);
         socket = hostServer.accept();
         Thread t = new Thread(n);
         t.start();
}
// If guest, try to connect to the server
else {
        socket = new Socket(hostIP, port);

}

Look at this code , think what was happning
in this code , in nutshell let me explain ,

when you wants to start the chat with your friend , your machine localhost is act like a server and your friend is just accepting that incomming connection . and when your friend is starting the chat then his computer was act like a server and you just act like a host .


so you have to change the code to always connects to a dedicated server and that server should be programmed to route and forward messages . then you are post your message to the server , and the server will post it to all the clients currently chatting except you . so change the code to do that .

if you dont know who to use the watch points and breakpoints lean debugging first , that is very useful when you are developing more complex software .
use the netbeans , that will help you to debug with a GUI , otherwise you have to go to the command prompt . so
http://debuggercore.netbeans.org/nonav/sourcesDemo.html
may be help you

I am not even trying to connect to friends yet. I am just trying to runn multiple clients on my own computer and connect them all to myself. Except only one connects.

But what you said defeats my purpose. I also want the server to be able to communicate to clients, not just relay messages.

Otherwise, if multiple people used it, one person would have to run a client and a server on the same computer.

"when you wants to start the chat with your friend , your machine localhost is act like a server and your friend is just accepting that incomming connection ."

I thought that the server accepts the incoming connections.

And I am currently using Eclipse, don't want to change mid project, so there has to be a way.

If you were knowledgeable about how Servers operated in Java, you wouldn't have this problem.

Really, this is nothing more than I/O with either streams or packets.

The scenario can be one of many.

If you're the Server, you wait for incoming Clients. The server can support a finite number of clients at its current location. You specify a port number for the Server to use, and typically the port number is set to a number that is not in use and that is valid.

If you're a Client, you can connect to a Server. The Client specifies the IP address the Server is located at and the port number. The IP address, I suppose is the home-base of the Server and the port number is the valid port number the Server is using.

Yes, this means you can have multiple Servers on one computer (by specifying different ports at the same IP).

Yes this means you can have multiple Clients per Server (where each client's action is listened for by the Server).

I do not know if a pure Client-to-Client connection can be made (in theory it seems possible but I haven't tried it yet) but unless you're incredibly proficient with Client/Servers I wouldn't recommend it (biased opinion since I'm fairly new to this myself).

What I do know is that if you want to make your program accept multiple Servers, and do so Concurrently, I'd assume that you would provide a Threaded Client that had a reference to a non-null server, where the non-null server would block and wait for the Client to connect.

This is a guess based on what I know about Client/Servers (just recently covered it in a class). Basically the Server will be capable of blocking for two Clients and accept communications from both at the same time through separate input and output stream handles to the specific Clients.

Each Client (Socket, or any class that derives from the Socket class) has something called getInputStream and getOutputStream methods. These methods are particularly useful for directly sending or receiving information from the Streams of the Clients. The Server can use these to communicate with the Clients by (if your Server is your main application) stuffing information in a Stream continuously and/or receiving information from a Stream continuously. Which Stream the Server looks at is entirely up to you. You'll just need to be in an environment capable of constantly checking the input and output streams of the Clients (through a while loop, a swing object, or a personal dedicated Thread for doing so).

Now to send and receive information seems in reverse to what you do with File I/O. The Server acts like the "receiving file" and the Client acts as a user that's writing and/or reading information to the file.

For example, the Client's output stream is the data the client is receiving as output, and the Client's input stream is the Client's way of sending information via input.

Understanding this concept is fundamental. Basically if the Client's way of sending information is the input stream, we can intercept it as the Server and find out what it is sending by waiting for information returned by the input stream (a call to the Client's input stream usually blocks until information is entered in the stream - basically you're like a file waiting for information to be written to you, is you're the Server). If we want the Client to see information, we can intercept the output stream for the specific Client and send information to the Client.

Now if you understand the concept of---

-Running Multiple Threads.
-How the Server works.

--mentioned above, You should be capable of establishing a multi-threaded environment for your Client/Server.

You may (or may not) have to do the research, but the concept is fairly obvious. I'll leave it to you to figure it out. Good luck!

The concept isn't hard to understand. I don't take a class, but I researched it all myself and that isn't the problem I am having. My goal was to make 1 server, and run multiple clients. Not multiple servers, and I didn't even expand over the simple network yet.

Currently, I have one computer trying to connect all clients to a server.
IP is just local host, because I am only doing it on my own computer. What I don't get is why new threads aren't forming after one client connects.

I thought it was the server's job to start new threads, but okay, I will give it a go with the clients. Although the user before said something was incorrect with my server code.

I picked up Java on my own, and started around June, so I am not exactly sure what he meant by debugging. I mean, there are no errors in the program, so I don't exactly understand how debugging will aid me. It just runs the program for me.

The concept isn't hard to understand. I don't take a class, but I researched it all myself and that isn't the problem I am having. My goal was to make 1 server, and run multiple clients. Not multiple servers, and I didn't even expand over the simple network yet.

Currently, I have one computer trying to connect all clients to a server.
IP is just local host, because I am only doing it on my own computer. What I don't get is why new threads aren't forming after one client connects.

I thought it was the server's job to start new threads, but okay, I will give it a go with the clients. Although the user before said something was incorrect with my server code.

I picked up Java on my own, and started around June, so I am not exactly sure what he meant by debugging. I mean, there are no errors in the program, so I don't exactly understand how debugging will aid me. It just runs the program for me.

It looks to me like the server only creates one socket and uses one port at a time. One guest program and one server program connect through that socket. I'm no expert on sockets and I could be off, but I don't think a third program can join a socket that's already being used between two other programs. Seems to me that if you have two clients, you need two sockets and two ports. If you have three clients, you need three sockets and three ports. Do you ever create a second socket? I don't see anywhere on the server's GUI where it can specify a second port to use for a second socket. I'm still figuring out why exactly it says "Connected" when the second client tries to join the original socket, but I don't think it is actually connected. If you're only using one port, I think you can only have one socket, and if you only have one socket, I think you can only have one client. Like I said, my knowledge of sockets is somewhat limited, but I think that's the way it is and I don't see the GUI allowing the server port ever to change without the server breaking the original socket's connection.

OKay thanks. I will look into that, fooling around with multiple sockets.

The concept isn't hard to understand. I don't take a class, but I researched it all myself and that isn't the problem I am having. My goal was to make 1 server, and run multiple clients. Not multiple servers, and I didn't even expand over the simple network yet.

Currently, I have one computer trying to connect all clients to a server.
IP is just local host, because I am only doing it on my own computer. What I don't get is why new threads aren't forming after one client connects.

I thought it was the server's job to start new threads, but okay, I will give it a go with the clients. Although the user before said something was incorrect with my server code.

I picked up Java on my own, and started around June, so I am not exactly sure what he meant by debugging. I mean, there are no errors in the program, so I don't exactly understand how debugging will aid me. It just runs the program for me.

What I do know is that if you want to make your program accept multiple Clients, and do so Concurrently, I'd assume that you would provide a Threaded Client that had a reference to a non-null server, where the non-null server would block and wait for the Client to connect.

I goofed - I meant multiple clients @_@

OKay thanks. I will look into that, fooling around with multiple sockets.

Let me actually clarify/correct my previous post, and reiterate that I'm somewhat out of my league on sockets. I've written a single-server, multi-client socket program successfully, but usually screw up a few times in the process and get Socekt and ServerSocket confused, so I'm going to offer this post and then shut up. Your ServerSocket should keep the same port for clients to try to connect to. Each time ServerSocket.accept() is executed, a new Socket should be created by the ServerSocket. That Socket will be assigned a port. All further message passing should go down that Socket, so that Socket can't have port 1337, since that's the ServerSocket's port, and all new Sockets need to have different ports from each other and different ports from 1337. Put some debugging statements in to make sure that's the case. So I think that if you have three programs going and connecting, you end up with five different ports used and two sockets total. The server uses three of the ports (1337 plus two random ones chosen by Java and not specified by you, let's say 1338 and 1339) and client 1 will have a different port, say 1340, and client 2 will have a different port, say 1341. The only port you've specified is 1337.

Socket 1 will connect ports 1338(server) and 1340(client 1).
Socket 2 will connect ports 1339(server) and 1341(client 2).

Port 1337 is reserved for the initial connection and remains the same since the clients need to have a constant port to connect to.

I can't get your program to run at all now, even with one client, which is weird since it worked before, so I can't verify this, so let me add again that I'm no socket pro so double-check with the documentation. But also check out this link towards the bottom. Best of luck.

http://java.sun.com/docs/books/tutorial/networking/sockets/clientServer.html

Doesn't an echo server have different functions though ? :S

This is too mind boggling, I am about to take a Java Class.

Ok, here is a small example of a multi-threaded server that I was playing around with a little while working on an auto-update launcher for an app here, maybe it will help. "Launcher" is the client portion. Each needs to be run separately on the same machine (since the client is connecting to localhost in the example)
Server:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Server {
    final static int PORT = 12100;
    Thread processThread;
    
    public Server() {
        try {
            processThread = new ProcessThread(new ServerSocket(PORT));
            processThread.start();
        } catch(IOException ex) {
            ex.printStackTrace();
        }
    }
    
    private class ProcessThread extends Thread {
        ServerSocket server;
        ExecutorService requestPool;
        
        public ProcessThread(ServerSocket server){
            this.server = server;
            requestPool = Executors.newCachedThreadPool();
        }
        
        public void run() {
            try {
                System.out.println("server waiting to process..");
                while(true) {
                    Socket sock = server.accept();
                    // start an UpdateTask for this client
                    requestPool.submit(new UpdateTask(sock));
                    sleep(100);
                }
            } catch(IOException ex) {
                ex.printStackTrace();
            } catch(InterruptedException e) {
                   // Disable new tasks from being submitted
                   requestPool.shutdown(); 
                   try {
                     // Wait a while for existing tasks to terminate
                     if (!requestPool.awaitTermination(60, TimeUnit.SECONDS)) {
                       // Cancel currently executing tasks
                       requestPool.shutdownNow(); 
                       // Wait a while for tasks to respond to being cancelled
                       if (!requestPool.awaitTermination(60, TimeUnit.SECONDS))
                           System.err.println("Pool did not terminate");
                     }
                   } catch (InterruptedException ie) {
                     // (Re-)Cancel if current thread also interrupted
                     requestPool.shutdownNow();
                     // Preserve interrupt status
                     Thread.currentThread().interrupt();
                   }
                Thread.currentThread().interrupt();
            }
        }
    }
    
    public void shutdown(){
        if (processThread != null && processThread.isAlive()){
            processThread.interrupt();
        }
    }
    
    /** This is the task that will be executed for each client 
     *  on the CachedThreadPool */
    private class UpdateTask implements Callable<String> {
        Socket client;
        String clientName;
        
        public UpdateTask(Socket client){
            this.client = client;
        }
        public String call() throws Exception {
            BufferedReader rd = new BufferedReader(
              new InputStreamReader(client.getInputStream()));
            PrintWriter wr = new PrintWriter(
              new OutputStreamWriter(client.getOutputStream()),true);
            
            // process input from the client
            String str;
            while ((str = rd.readLine()) != null) {
                System.out.println(str);
                if (str.endsWith("calling")){
                    clientName = str.substring(0,str.indexOf(" calling"));
                    wr.println("Go ahead, "+clientName);
                }
                if (str.startsWith("update")){
                    wr.println("updating "+clientName);
                }
                if (str.startsWith("got it")){
                    wr.println("bye "+clientName);
                }
            }
            rd.close();
            System.out.println(clientName+" finished");
            return "Ok, done";
        }
    }
    
    public static void main(String[] args) {
        new Server();
    }
}

Client:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

public class Launcher {

    final static int PORT = 12100;
    String client;

    public Launcher(String client) {
        this.client = client;
        
        // Create a socket with a timeout
        try {
            InetAddress addr = InetAddress.getByName("localhost");
            int port = 12100;
            SocketAddress sockaddr = new InetSocketAddress(addr, port);

            // Create an unbound socket
            Socket sock = new Socket();

            // This method will block no more than timeoutMs.
            // If the timeout occurs, SocketTimeoutException is thrown.
            int timeoutMs = 2000;   // 2 seconds
            sock.connect(sockaddr, timeoutMs);
            System.out.println(client+" connected");
            
            PrintWriter wr = new PrintWriter(
              new OutputStreamWriter(sock.getOutputStream()), true);
            BufferedReader rd = new BufferedReader(
              new InputStreamReader(sock.getInputStream()));

            // send something to server
            wr.println(client+" calling");

            // read server response
            String str;
            while((str = rd.readLine())!=null) {
                System.out.println(str);
                if (str.startsWith("Go ahead")){
                    wr.println("update me");
                }
                if (str.startsWith("updating")){
                    wr.println("got it");
                }
                if (str.startsWith("bye")){
                    break;
                }
            }
            
            rd.close();
            wr.close();
            sock.close();
        } catch(UnknownHostException e) {
            e.printStackTrace();
        } catch(SocketTimeoutException e) {
            e.printStackTrace();
        } catch(IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        // start up two client threads
        new Thread(new Runnable() {
            public void run() {
                new Launcher("Bob");
            }
        }).start();
        
        new Thread(new Runnable() {
            public void run() {
                new Launcher("Mary");
            }
        }).start();
    }
}
commented: Thank you for providing an example =) +2

I know the answer was probably already given but I made this simple chatting program from scratch.

It is a test - it does NOT cover things such as recycling threads that are no longer used when a client disconnects, nor is there any true exception handling when a client disconnects.

Also there is a flag-type system in this practice program that disables the same input from being entered twice. That can easily be removed, but it was only implemented because the original program (modified) sent information to the Server as if it were a type of information-storage unit (or a very watered down database).

Here's the code.

import java.io.*; // for ObjectInputStream and ObjectOutputStream classes
import java.net.*; // for Socket and ServerSocket classes
import java.util.*; // for a Scanner object
import java.util.concurrent.*; // for Executors and ExecutorService classes

public class ChatServer{

	private ServerSocket ss;
	private Socket theClient[];
	private ObjectInputStream ois[];
	private ObjectOutputStream oos[];
	private ChatServer cs = this;
	private String information = "No information", oldInformation = "No information";
	private boolean update = false;
	private static int numClients = 0;
	private int index = 0;
	static{
		System.out.println("Setting up a test server...");
		System.out.println("How many clients would you like to connect to the server? ");
		numClients = new Scanner(System.in).nextInt();
	}
	private ExecutorService es;

	public static void main(String... args){

		ChatServer myCS = new ChatServer();

		while(true){
			if(!myCS.information.equalsIgnoreCase(myCS.oldInformation)){
				myCS.oldInformation = new String(myCS.information);
				myCS.update = true;
			}

			for(ObjectOutputStream element : myCS.oos){
				if((element != null) && myCS.update){
					try{
						element.writeObject(myCS.information + "\n");
					}catch(Exception e){e.printStackTrace();}
				}else continue;
			}
			myCS.update = false;
		}
	}

	public ChatServer(){

		/*
		 * Server should block for clients
		 * and wait for a connection of at least
		 * one client before displaying information
		 */

		try{
			ss = new ServerSocket(6000, numClients); // creates the server at this address, with port 6000 and portQueue numClients
			theClient = new Socket[numClients]; // makes room for numClients amount of clients
			ois = new ObjectInputStream[numClients]; // makes room for numClients amount of ObjectInputStreams
			oos = new ObjectOutputStream[numClients]; // makes room for numClients amount of ObjectOutputStreams
			es = Executors.newFixedThreadPool(numClients);
		}catch(Exception e){e.printStackTrace(); System.exit(1);} // prints the location of the Exception

		for(int i = 0; i < numClients; i++){
			try{
				es.submit(new MyThread());
			}catch(Exception e){e.printStackTrace();}
		}
	}

	private void sleep(long milliseconds){
		try{Thread.sleep(milliseconds);}catch(Exception e){}
	}

	private class MyThread implements Runnable{
		int x = 0;

		@Override
		public void run(){

			/*Aquires a lock for the out-class - locks other threads from executing until this automic action is finished*/
			synchronized(cs){
				x = index++;
				System.out.println(x);
				try{
					theClient[x] = ss.accept();
					oos[x] = new ObjectOutputStream(theClient[x].getOutputStream());
					oos[x].flush();
					ois[x] = new ObjectInputStream(theClient[x].getInputStream());
				}catch(Exception e){e.printStackTrace();}
			}

			while(true){
				System.out.println("Blocking for client number: " + x);
				try{
					information = (String)ois[x].readObject();
					System.out.println("Got new information!");
				}catch(Exception e){e.printStackTrace();}
			}
		}
	}
}
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.concurrent.*;

public class SomeClient extends JFrame implements ActionListener{

	private Socket me;
	private ObjectInputStream ois;
	private ObjectOutputStream oos;
	private JTextArea jta;
	private JTextField jtf;
	private ExecutorService es;

	public SomeClient(){

		setSize(600, 400);
		setLayout(new BorderLayout());

		jta = new JTextArea();
		jta.setEditable(false);
		add(BorderLayout.CENTER, jta);

		jtf = new JTextField(30);
		jtf.setEditable(true);
		jtf.setActionCommand("JTF");
		jtf.addActionListener(this);
		add(BorderLayout.SOUTH, jtf);

		try{
			me = new Socket("127.0.0.1", 6000);
			oos = new ObjectOutputStream(me.getOutputStream());
			oos.flush();
			ois = new ObjectInputStream(me.getInputStream());
		}catch(Exception e){e.printStackTrace();}
		es = Executors.newFixedThreadPool(1);
		es.submit(rt);
	}

	Runnable rt = new Runnable(){
		@Override
		public void run(){
			while(true){
				try{
					jta.append((String)ois.readObject());
				}catch(Exception e){e.printStackTrace();}
			}
		}
	};

	public static void main(String... args){
		SomeClient sc = new SomeClient();
		sc.setVisible(true);
	}

	public void actionPerformed(ActionEvent e){

		if(e.getActionCommand().equalsIgnoreCase("JB")){
		}
		else if(e.getActionCommand().equalsIgnoreCase("JTF")){
			try{
				oos.writeObject("<" + me.toString() + "> " + jtf.getText());
				oos.flush();
				jtf.setText("");
			}catch(Exception e2){e2.printStackTrace();}
		}
	}
}

It can use a lot of work but it gets some of the main points of network + multi-threading across.

Edit: Looking back at the code, I think that the call to accept() should not be synchronized, but the increment of index should be at least.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.