Connect two client sockets

前端 未结 12 1490
执笔经年
执笔经年 2020-12-10 03:58

Let\'s say Java has two kind of sockets:

  • server sockets \"ServerSocket\"
  • client sockets or just \"Socket\"

Imagine the situation of two

12条回答
  •  情歌与酒
    2020-12-10 04:15

    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 future1;
        private Future 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() {
    
                    @Override
                    public Boolean call() throws Exception {
                        try {
                            processConnection(input1);
                            displayMessage("input1 finished");
                        } catch (IOException e) {
                            displayMessage("blah");
                        }
                        return true;
                    }
                });
                future2 = service.submit(
                        new Callable() {
    
                    @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")
    //                           
    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();
    }//                         
    
    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.

提交回复
热议问题