无服务器套接字侦听的Java套接字连接

无服务器套接字侦听的Java套接字连接,java,sockets,serversocket,Java,Sockets,Serversocket,这是我连接两个套接字的代码,没有任何服务器套接字: package primary; import java.awt.FlowLayout; import java.io.EOFException; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.InetAddress; import java.net.ServerS

这是我连接两个
套接字
的代码,没有任何
服务器套接字

package primary;

import java.awt.FlowLayout;
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;
    }

    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);
        setLayout(new FlowLayout());
        dataField.setEditable(false);
        dataField.setColumns(20);
        dataField.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                dataFieldActionPerformed(evt);
            }
        });

        sendButton1.setText("Send Object 1");
        sendButton1.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                sendButton1ActionPerformed(evt);
            }
        });

        sendButton2.setText("Send Object 2");
        sendButton2.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                sendButton2ActionPerformed(evt);
            }
        });

        resultArea.setColumns(25);
        resultArea.setRows(15);
        resultArea.setEditable(false);
        resultArea.setRows(5);
        jScrollPane1.setViewportView(resultArea);

        add(dataField);
        add(sendButton1);
        add(sendButton2);
        add(jScrollPane1);
        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);
    }                                  

    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");
        }
    }

    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;
}
这里的
Object1
Object2
只是两个可序列化的对象。看起来所有的插座都连接得很好。如果我退出系统而不调用套接字及其输入、输出流的close()方法并重新运行,它仍然可以正常工作。但如果我在确保调用close()方法后退出系统,然后再次运行,我会得到以下结果: 1客户端2地址已在使用中:连接

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
我一次又一次地重新运行,我一直得到这个,除非,我等待一定的时间,然后再次运行,它就像第一次一样正常。 为什么会发生这样的事情?为什么我关上插座要花这么多时间,而不是在不关插座的时候?当我不关闭插座时,它们是真的关闭了还是仅仅连接了现有的连接?但是当使用
ServerSocket
时,在我关闭的情况下似乎不会发生这种情况。到底发生了什么


另一个问题是,
ServerSocket
应该将它的
Socket
连接的末端交给一个本地端口,而不是它正在侦听的端口。如果这是真的,为什么在调用Socket.getLocalPort()时,为它接受的所有套接字获取侦听localport?

在创建
套接字时,不要使用第3个和第4个参数。除了VPN之外,没有真正的需要指定本地地址,也没有真正的需要指定本地端口,除非是netadmin虚构的

ServerSocket应该将其套接字端连接分发给它正在侦听的本地端口以外的其他端口


不,没有。所有接受的套接字使用与侦听端口相同的本地端口。

在创建
套接字时,不要使用第3个和第4个参数。除了VPN之外,没有真正的需要指定本地地址,也没有真正的需要指定本地端口,除非是netadmin虚构的

ServerSocket应该将其套接字端连接分发给它正在侦听的本地端口以外的其他端口


不,没有。所有接受的套接字都使用与侦听端口相同的本地端口。

调用所有close方法后,我使用
netstat-ao
查看端口的状态。它显示每个连接的一个端口(即使用的6个端口中的3个)处于
TIME\u WAIT
状态。为什么?试着读这篇文章。在意识到我先前的回答不正确后,我发现这一点:。(删除了不正确的答案)。调用所有close方法后,我使用
netstat-ao
查看端口的状态。它显示每个连接的一个端口(即使用的6个端口中的3个)处于
TIME\u WAIT
状态。为什么?试着读这篇文章。在意识到我先前的回答不正确后,我发现这一点:。(删除了不正确的答案)。我不知道你的意思。第三个和第四个似乎是必要的,因为Somnone需要先绑定到其localport,然后其他人才能将其作为远程端口连接。请注意,此代码中没有
ServerSocket
。我在互联网上找不到这种
ServerSocket
less代码(有些是客户端或没有定义服务器的P2P)。@mustansir我说的正是我的意思。“在创建套接字时不要使用第3个和第4个参数。”您关于它们看起来必要的理由是不正确的。将出站套接字绑定到本地端口不会创建其他人可以绑定到的侦听套接字。在Java中实现这一点的唯一方法是使用
ServerSocket。
如果我注释掉第3个和第4个参数,它就不起作用了。你建议如何实现P2P通信?@mustansir无论有没有参数,它都不起作用,因为整个概念都是错误的。你不能用TCP实现P2P,你必须使用一个
ServerSocket,
,正如我已经说过的。指定本地ip:端口只会导致进一步的问题。我不确定你的意思。第三个和第四个似乎是必要的,因为Somnone需要先绑定到其localport,然后其他人才能将其作为远程端口连接。请注意,此代码中没有
ServerSocket
。我在互联网上找不到这种
ServerSocket
less代码(有些是客户端或没有定义服务器的P2P)。@mustansir我说的正是我的意思。“在创建套接字时不要使用第3个和第4个参数。”您关于它们看起来必要的理由是不正确的。将出站套接字绑定到本地端口不会创建其他人可以绑定到的侦听套接字。在Java中实现这一点的唯一方法是使用
ServerSocket。
如果我注释掉第3个和第4个参数,它就不起作用了。你建议如何实现P2P通信?@mustansir无论有没有参数,它都不起作用,因为整个概念都是错误的。你不能用TCP实现P2P,你必须使用一个
ServerSocket,
,正如我已经说过的。指定本地ip:端口只会导致进一步的问题。
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