简体   繁体   English

两个不同的套接字实例可以侦听相同的TCP端口(端口已在使用中)

[英]Can two different socket instances listen to same TCP port ( Port already in use )

I have a TcpServer class that is responsible to, well, act like a tcp server. 我有一个TcpServer类负责,就像tcp服务器一样。 You can find the class below : 你可以在下面找到这个课程:

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

And I have a code piece that does this : 我有一个代码片来做到这一点:

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

However I am getting a port already in use error. 但是我得到一个端口已经在使用错误。 I thought two different socket instances could listen to the same port as multiplexing allows two connections through the same port when the connector has different ip or port ? 我认为两个不同的套接字实例可以监听同一个端口,因为当连接器有不同的ip或端口时,多路复用允许两个连接通过同一个端口? What am I missing? 我错过了什么?

You cannot bind two tcp server sockets to the same port. 您不能将两个tcp服务器套接字绑定到同一端口。 reuseAddress is really for client sockets, and it does not work the way you think it does ... and the way you are using it would not do anything at all either way (because you are setting it after binding). reuseAddress是用于客户端套接字,并且它不像你想象的那样工作......并且你使用它的方式根本不会做任何事情(因为你在绑定后设置它)。

You don't really need to bind twice to the same port either. 你真的不需要两次绑定到同一个端口。 Just remove this line tcpServer = new TcpServer(LocalPort); 只需删除此行tcpServer = new TcpServer(LocalPort); from the bottom of your while loop, and you'll be all set. 从你的while循环的底部,你将全部设置。

The way this works is that you bind your server socket once and listen to the port. 这种方式的工作方式是绑定服务器套接字一次并监听端口。 When a connection arrives, it forks a client socket for you to communicate with the client, and the original server socket continues to listen for more connections. 当连接到达时,它会分叉客户端套接字以便您与客户端通信,并且原始服务器套接字继续侦听更多连接。

Basically, you need to remove the socket member (and any other state) from your TcpServer , and make the accept method return the accepted socket. 基本上,您需要从TcpServer删除socket成员(以及任何其他状态),并使accept方法返回接受的套接字。 Then make your runnable take that socket as a parameter instead of the TcpServer , and use that to serve the client connection. 然后让runnable将该socket作为参数而不是TcpServer ,并使用它来为客户端连接提供服务。 Then just keep calling accept in the loop, and forking threads for new connections same way you do know, except do not recreate the server every time. 然后继续在循环中调用accept ,并以您知道的方式为新连接分叉线程,除非每次都不重新创建服务器。

Or, alternatively, remove the server socket and port from TcpServer , create the socket outside the loop, then while(true) call accept on it, create a new TcpServer with the returned client socket, and use it in a thread to process the connection. 或者,或者从TcpServer删除服务器套接字和端口,在循环外创建套接字,然后while(true)调用accept ,使用返回的客户端套接字创建一个新的TcpServer ,并在线程中使用它来处理连接。

Do not forget to close client sockets after you are done with them. 完成后,不要忘记关闭客户端套接字。

No, you can't use a port already in listening state. 不,您不能使用已处于侦听状态的端口。 However any number of clients can connect to this same port. 但是,任意数量的客户端都可以连接到同一个端口。 You don't need to listen to the port again, you just spawn a new thread to process the current connection and wait for a new one. 您不需要再次侦听端口,只需生成一个新线程来处理当前连接并等待新连接。 For example, supposing you have a class TcpConnectionHanlder that implements Runnable and takes the Socket as parameter, the loop would look like 例如,假设您有一个实现Runnable的类TcpConnectionHanlder并将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.
}

Then in your TcpConnectionHanlder instance you handle this particular client (socket). 然后在您的TcpConnectionHanlder实例中处理此特定客户端(套接字)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 系统中的两个不同的 UDP 套接字可以绑定同一个端口吗? - Can two different UDP socket in a system bind same port? 两个线程可以在同一个端口中调用一个新的套接字(客户端套接字)吗? - Can two threads call a new socket (client socket) in the same port? 使用相同的TCP端口进行接受和连接 - Use same TCP port for accept and connect 通过Java套接字侦听端口 - Listen to port via a Java socket 两个具有相同端口和地址的套接字实例 - two instance of socket with same port and address 两个进程侦听同一个端口(使用 Jersey),但不响应相同的请求 - Two processes listen on the same port (using Jersey), but not responding to same requests 线程套接字处理程序,用于在TCP端口中进行双向通信 - Threading socket handler for two sided communication in tcp port 可以在Maven payara-micro-maven-plugin中设置端口,避免“address already in use”运行多个实例吗? - Can the port be set in the Maven payara-micro-maven-plugin to avoid "address already in use" running multiple instances? 配置为侦听端口 8080 的 Tomcat 连接器无法启动。 端口可能已在使用中或连接器可能配置错误 - The Tomcat connector configured to listen on port 8080 failed to start. The port may already be in use or the connector may be misconfigured 我收到 java.net.BindException: Address already in use: 当我尝试侦听并将客户端绑定到同一端口时绑定 - I'm getting java.net.BindException: Address already in use: bind when i try to listen and bind a client to same port
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM