【问题标题】:Can two different socket instances listen to same TCP port ( Port already in use )两个不同的套接字实例能否监听同一个 TCP 端口(端口已在使用中)
【发布时间】:2015-01-26 14:24:58
【问题描述】:

我有一个 TcpServer 类,它负责充当 tcp 服务器。您可以在下面找到课程:

public class TcpServer {
    private ServerSocket serverSocket;
    private Socket socket;
    private int locallyBoundPort;

    public TcpServer() {


    }

    public TcpServer(int locallyBoundPort) {
        try {
            this.serverSocket = new ServerSocket(locallyBoundPort);
            serverSocket.setReuseAddress(true);
        } catch (IOException e) {
            System.out.println("Error at binding to port TCP : " + locallyBoundPort + "...cause : " + e.getMessage());
        }
        socket = null;

    }

    public void accept() {
        try {
            socket = serverSocket.accept();
            socket.setReuseAddress(true);
        } catch (IOException e) {
            System.out.println("Error at accept : " + locallyBoundPort);
        }
    }



    public void send(Data data) throws IOException {
        if(socket != null) {

            ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
            out.writeObject(data);

        }
    }

    public Data receive() throws ClassNotFoundException, IOException {
        if(socket != null) {

                ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
                return (Data) in.readObject();

        } else {
            return null;
        }
    }

    public boolean bind(int port) throws IOException {
        try {
            this.serverSocket = new ServerSocket(port);
            this.locallyBoundPort = port;
        } catch(IOException e) {
            return false;
        }
        return true;

    }

    public void close() {
        try {
            serverSocket.close();
            socket.close();
        } catch (IOException e) {
            OzumUtils.print("IOException in close, TcpServer");
        }

    }

    public int getLocallyBoundPort() {
        return locallyBoundPort;
    }

    public Socket getSocket() {
        return socket;
    }

    public ServerSocket getServerSocket() {
        return serverSocket;
    }
}

我有一段代码可以做到这一点:

TcpServer tcpServer = new TcpServer(LocalPort);
while(1)
{
    tcpServer.accept();
    Thread thread = new Thread(new runnable(tcpServer));
    thread.start();
    tcpServer = new TcpServer(LocalPort);
}

但是我收到端口已在使用错误。我认为两个不同的套接字实例可以监听同一个端口,因为当连接器具有不同的 ip 或端口时,多路复用允许两个连接通过同一个端口? 我错过了什么?

【问题讨论】:

  • 不,你不能使用已经处于监听状态的端口。但是,任何数量的客户端都可以连接到同一个端口。

标签: java sockets tcp


【解决方案1】:

您不能将两个 tcp 服务器套接字绑定到同一个端口。 reuseAddress 确实适用于客户端套接字,它不会像您认为的那样工作......而且您使用它的方式根本不会做任何事情(因为您是在绑定后设置它)。

您也不需要将两次绑定到同一个端口。只需从while 循环的底部删除这一行tcpServer = new TcpServer(LocalPort);,就可以了。

它的工作方式是绑定一次服务器套接字并监听端口。当一个连接到达时,它会分叉一个客户端套接字供你与客户端通信,而原来的服务器套接字会继续监听更多的连接。

基本上,您需要从TcpServer 中删除socket 成员(和任何其他状态),并使accept 方法返回接受的套接字。然后让您的runnablesocket 作为参数而不是TcpServer,并使用它来服务客户端连接。然后在循环中继续调用accept,并以你知道的方式为新连接分叉线程,但不要每次都重新创建服务器。

或者,或者,从TcpServer 中删除服务器套接字和端口,在循环外创建套接字,然后 while(true) 在其上调用 accept,使用返回的客户端套接字创建一个新的 TcpServer,然后使用它在一个线程中处理连接。

完成后不要忘记关闭客户端套接字。

【讨论】:

  • 你好。感谢您的详细回复。让我再问你一件事来澄清一下。你是说当一个 TCP 套接字接受一个连接时,它可以同时接受其他连接器,并保持与以前的连接器通信?哦,在我写这篇文章时,我意识到这就是当 ServerSocket 接受连接器时返回新套接字的原因。谢谢!
【解决方案2】:

不,您不能使用已处于侦听状态的端口。但是,任意数量的客户端都可以连接到同一端口。您不需要再次监听端口,只需生成一个新线程来处理当前连接并等待新的连接。例如,假设你有一个类 TcpConnectionHanlder 实现了 Runnable 并以 Socket 作为参数,循环看起来像

while (true) { //while(1) is not valid Java syntax
    final Socket tcpSocket = tcpServer.accept(); // Get socket for incoming connection
    final Thread thread = new Thread(new TcpConnectionHanlder(tcpSocket)); // Create a thread for this socket/client connection
    thread.start(); // Launch the thread
    // tcpServer = new TcpServer(LocalPort); <- not needed, port still listening.
}

然后在您的 TcpConnectionHanlder 实例中处理这个特定的客户端(套接字)。

【讨论】:

    猜你喜欢
    • 2019-02-20
    • 1970-01-01
    • 1970-01-01
    • 2017-06-09
    • 2012-06-13
    • 2014-10-31
    • 1970-01-01
    • 2012-06-23
    相关资源
    最近更新 更多