This is the code where I connected two Socket without any ServerSocket:
package primary; import javax.swing.JFrame; import javax.swing.SwingUtilities; public class Main { private static Object locker; public static void main(String[] args) { locker = new Object(); final int[][] a = new int[6][]; final int[][] b = new int[6][]; final int[][] c; a[0] = new int[] {12340, 12341}; a[1] = new int[] {12342, 12344}; a[2] = new int[] {12342, 12343}; a[3] = new int[] {12340, 12345}; a[4] = new int[] {12344, 12345}; a[5] = new int[] {12341, 12343}; b[0] = new int[] {22340, 22341}; b[1] = new int[] {22342, 22344}; b[2] = new int[] {22342, 22343}; b[3] = new int[] {22340, 22345}; b[4] = new int[] {22344, 22345}; b[5] = new int[] {22341, 22343}; c = a; SwingUtilities.invokeLater( new Runnable() { @Override public void run() { Client client1 = new Client("client1", c[0], c[1]); client1.exe(); client1.setLocation(0, 200); client1.setVisible(true); client1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } }); SwingUtilities.invokeLater( new Runnable() { @Override public void run() { Client client2 = new Client("client2", c[2], c[3]); client2.exe(); client2.setLocation(400, 200); client2.setVisible(true); client2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } }); SwingUtilities.invokeLater( new Runnable() { @Override public void run() { Client client3 = new Client("client3", c[4], c[5]); client3.exe(); client3.setLocation(800, 200); client3.setVisible(true); client3.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } }); } }
package primary; import java.io.EOFException; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; import java.util.concurrent.*; import javax.swing.JFrame; import javax.swing.SwingUtilities; public class Client extends JFrame implements Runnable { private final String myName; private ServerSocket listener; private Socket connection1; private Socket connection2; private ObjectOutputStream output1; private ObjectOutputStream output2; private ObjectInputStream input1; private ObjectInputStream input2; private Object receiveObject; private Object1 sendObject1; private Object2 sendObject2; private final int[] myLocalPort; private final int[] connectionPort; private ExecutorService service; private Future<Boolean> future1; private Future<Boolean> future2; public Client(final String myName, int[] myLocalPort, int[] connectionPort) { super(myName); this.myName = myName; this.myLocalPort = myLocalPort; this.connectionPort = connectionPort; sendObject1 = new Object1("string1", "string2", myName); sendObject2 = new Object2("string1", 2.5, 2, true, myName); initComponents(); } public void exe() { ExecutorService eService = Executors.newCachedThreadPool(); eService.execute(this); } @Override public void run() { try { displayMessage("Attempting connection\n"); try { connection1 = new Socket(InetAddress.getByName("localhost"), connectionPort[0], InetAddress.getByName("localhost"), myLocalPort[0]); displayMessage(myName + " connection1\n"); } catch (Exception e) { displayMessage("failed1\n"); System.err.println("1" + myName + e.getMessage() + "\n"); } try { connection2 = new Socket(InetAddress.getByName("localhost"), connectionPort[1], InetAddress.getByName("localhost"), myLocalPort[1]); displayMessage(myName + " connection2\n"); } catch (Exception e) { displayMessage("failed2\n"); System.err.println("2" + myName + e.getMessage() + "\n"); } displayMessage("Connected to: " + connection1.getInetAddress().getHostName() + "\n\tport: " + connection1.getPort() + "\n\tlocal port: " + connection1.getLocalPort() + "\n" + connection2.getInetAddress().getHostName() + "\n\tport: " + connection2.getPort() + "\n\tlocal port: " + connection2.getLocalPort() + "\n\n"); output1 = new ObjectOutputStream(connection1.getOutputStream()); output1.flush(); output2 = new ObjectOutputStream(connection2.getOutputStream()); output2.flush(); input1 = new ObjectInputStream(connection1.getInputStream()); input2 = new ObjectInputStream(connection2.getInputStream()); displayMessage("Got I/O stream\n"); setTextFieldEditable(true); service = Executors.newFixedThreadPool(2); future1 = service.submit( new Callable<Boolean>() { @Override public Boolean call() throws Exception { try { processConnection(input1); displayMessage("input1 finished"); } catch (IOException e) { displayMessage("blah"); } return true; } }); future2 = service.submit( new Callable<Boolean>() { @Override public Boolean call() throws Exception { try { processConnection(input2); displayMessage("input2 finished"); } catch (IOException e) { displayMessage("foo"); } return true; } }); } catch (UnknownHostException e) { displayMessage("UnknownHostException\n"); e.printStackTrace(); } catch (EOFException e) { displayMessage("EOFException\n"); e.printStackTrace(); } catch (IOException e) { displayMessage("IOException\n"); e.printStackTrace(); } catch(NullPointerException e) { System.err.println("asdf " + e.getMessage()); } finally { try { displayMessage("i'm here\n"); if((future1 != null && future1.get()) && (future2 != null && future2.get())) { displayMessage(future1.get() + " " + future2.get() + "\n"); displayMessage("Closing Connection\n"); setTextFieldEditable(false); if(!connection1.isClosed()) { output1.close(); input1.close(); connection1.close(); } if(!connection2.isClosed()) { output2.close(); input2.close(); connection2.close(); } displayMessage("connection closed\n"); } } catch (IOException e) { displayMessage("IOException on closing"); } catch (InterruptedException e) { displayMessage("InterruptedException on closing"); } catch (ExecutionException e) { displayMessage("ExecutionException on closing"); } } }//method run ends private void processConnection(ObjectInputStream input) throws IOException { String message = ""; do { try { receiveObject = input.readObject(); if(receiveObject instanceof String) { message = (String) receiveObject; displayMessage(message + "\n"); } else if (receiveObject instanceof Object1) { Object1 receiveObject1 = (Object1) receiveObject; displayMessage(receiveObject1.getString1() + " " + receiveObject1.getString2() + " " + receiveObject1.toString() + "\n"); } else if (receiveObject instanceof Object2) { Object2 receiveObject2 = (Object2) receiveObject; displayMessage(receiveObject2.getString1() + " " + receiveObject2.getD() + " " + receiveObject2.getI() + " " + receiveObject2.toString() + "\n"); } } catch (ClassNotFoundException e) { displayMessage("Unknown object type received.\n"); } displayMessage(Boolean.toString(message.equals("terminate\n"))); } while(!message.equals("terminate")); displayMessage("finished\n"); input = null; } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code"> private void initComponents() { dataField = new javax.swing.JTextField(); sendButton1 = new javax.swing.JButton(); sendButton2 = new javax.swing.JButton(); jScrollPane1 = new javax.swing.JScrollPane(); resultArea = new javax.swing.JTextArea(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); dataField.setEditable(false); dataField.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { dataFieldActionPerformed(evt); } }); sendButton1.setText("Send Object 1"); sendButton1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { sendButton1ActionPerformed(evt); } }); sendButton2.setText("Send Object 2"); sendButton2.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { sendButton2ActionPerformed(evt); } }); resultArea.setColumns(20); resultArea.setEditable(false); resultArea.setRows(5); jScrollPane1.setViewportView(resultArea); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(jScrollPane1) .addComponent(dataField, javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() .addComponent(sendButton1) .addGap(18, 18, 18) .addComponent(sendButton2) .addGap(0, 115, Short.MAX_VALUE))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addComponent(dataField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(sendButton1) .addComponent(sendButton2)) .addGap(18, 18, 18) .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 144, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); pack(); }// </editor-fold> private void dataFieldActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: sendData(evt.getActionCommand()); dataField.setText(""); } private void sendButton1ActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: sendData(sendObject1); } private void sendButton2ActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: sendData(sendObject2); } /** * @param args the command line arguments */ private void displayMessage(final String messageToDisplay) { SwingUtilities.invokeLater( new Runnable() { @Override public void run() { resultArea.append(messageToDisplay); } }); } private void setTextFieldEditable(final boolean editable) { SwingUtilities.invokeLater( new Runnable() { @Override public void run() { dataField.setEditable(editable); } }); } private void sendData(final Object object) { try { output1.writeObject(object); output1.flush(); output2.writeObject(object); output2.flush(); displayMessage(myName + ": " + object.toString() + "\n"); } catch (IOException e) { displayMessage("Error writing object\n"); } } // Variables declaration - do not modify private javax.swing.JTextField dataField; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JTextArea resultArea; private javax.swing.JButton sendButton1; private javax.swing.JButton sendButton2; // End of variables declaration }
Here Object1 and Object2 are just two Serializable Objects. All the sockets connect perfectly, it seems. If I System.exit() without calling the close() methods for the sockets and their input, output streams and re-run, it works fine still. But if I System.exit() by making sure that the close() methods are called, and I re-run again, I get this:
1client2Address already in use: connect 1client3Address already in use: connect 2client3Address already in use: connect asdf null 1client1Connection refused: connect 2client2Connection refused: connect asdf null 2client1Connection refused: connect asdf null
I re-run again and again, I keep getting this, unless, I wait a certain amount of time and re-run again, it works just fine as the first time.