java - 两个不同的套接字实例是否可以监听同一个 TCP 端口(端口已在使用中)

标签 java sockets tcp

我有一个 TcpServer 类负责,嗯,就像一个 tcp 服务器。您可以在下面找到类(class):

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 或端口时,多路复用允许通过同一个端口进行两个连接? 我错过了什么?

最佳答案

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

你真的不需要两次绑定(bind)到同一个端口。只需从 while 循环底部删除此行 tcpServer = new TcpServer(LocalPort); 即可,一切就绪。

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

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

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

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

关于java - 两个不同的套接字实例是否可以监听同一个 TCP 端口(端口已在使用中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28151983/

相关文章:

Linux内核2.6中sock结构的变化?

c - 高性能TCP服务器架构

java - Vaadin Designer 不是可编辑的自定义组件

java - 使用数字签名来保护二维码

java - eclipse 中的 JUnit 面板

java - 使用 Mockito 测试抽象类

.net - TCP星型网络对等连接策略

c++ - 将 C/C++ 线程附加到套接字

c# - 有没有办法在可移植类库中创建套接字?

c# - Silverlight 中的异步套接字连接