Java 如何确保另一端的TCP套接字是否已关闭?(如何读取确认信号)

Java 如何确保另一端的TCP套接字是否已关闭?(如何读取确认信号),java,sockets,telnet,Java,Sockets,Telnet,考虑下面的java伪代码(clisent使用IP和端口23(telnet)打开服务器的套接字): …下面的异常有时会发生,因为我们正在尝试重新打开尚未完全关闭的同一个套接字 错误:java.io.IOException:连接重置 如何确保(检查)另一端的套接字已关闭?换句话说,在我们继续并在代码的另一部分中重新打开该套接字之前,等待服务器的确认。 -由于某种原因,我们必须重新打开同一个插座 -另外,我们对在重新打开同一个套接字之前放置延迟不感兴趣 简言之:我们希望读取服务器的确认(蓝线) 套接字

考虑下面的java伪代码(clisent使用IP和端口23(telnet)打开服务器的套接字):

…下面的异常有时会发生,因为我们正在尝试重新打开尚未完全关闭的同一个套接字 错误:java.io.IOException:连接重置

如何确保(检查)另一端的套接字已关闭?换句话说,在我们继续并在代码的另一部分中重新打开该套接字之前,等待服务器的确认。 -由于某种原因,我们必须重新打开同一个插座 -另外,我们对在重新打开同一个套接字之前放置延迟不感兴趣

简言之:我们希望读取服务器的确认(蓝线)


套接字由两端的IP和端口、源端口和目标端口标识。您的第二个连接应获得不同的源端口,因此被服务器视为一个单独的连接。确保服务器始终接受新连接,并且您应该正常。

打印客户端套接字的本地端口如果您为每个新的客户端套接字获得一个新的本地端口,那么“套接字重用”就不太可能出现问题,除非TCP堆栈中存在错误。顺便问一下,您是否通过例如或显式指定本地套接字号?您可能不应该这样做。让系统选择一个临时端口即可


问题可能出在服务器上,而不是客户端。当我关闭客户端套接字并立即将其重新创建到同一主机和端口时,我没有问题。在我退出之前,SSCCE已成功连接到130k个连接,没有问题。环回接口可能比真正的NIC更宽容,但您可以轻松修改此代码以在re上运行艾尔网络

public class TestTcpClientServer
{
    public static final int SERVER_PORT = 10111;

    public static void main(String[] args) throws Exception
    {
        Server server = new Server();
        server.start();

        Thread.sleep(500);

        Client client = new Client();
        client.start();

        System.out.println("Press enter to shutdown...");

        System.in.read();

        client.shutdown();
        client.join();
        server.shutdown();
        server.join();

        System.out.println("Done.");
    }

    public static class Client extends Thread
    {
        private volatile boolean shutdown = false;

        public void run()
        {
            try
            {
                int totalClientConnections = 0;

                while (!shutdown)
                {
                    Socket socket = new Socket("localhost", SERVER_PORT);

                    InputStream inputStream = socket.getInputStream();
                    BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));

                    OutputStream outputStream = socket.getOutputStream();
                    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outputStream));

                    bw.write("Client saying hello to server");
                    bw.newLine();
                    bw.flush();

                    String readLine = br.readLine();
                    //System.out.println("Client read from server: " + readLine);

                    System.out.println("Socket local port: " + socket.getLocalPort());

                    socket.close();

                    totalClientConnections++;
                    if (totalClientConnections % 10000 == 0)
                    {
                        System.out.println("totalClientConnections=" + totalClientConnections);
                    }

                    Thread.sleep(1000);
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }

        public void shutdown()
        {
            shutdown = true;
        }
    }

    public static class Server extends Thread
    {
        private volatile boolean shutdown = false;
        private ServerSocket serverSocket = null;

        public void run()
        {
            try
            {
                int totalServerConnections = 0;

                serverSocket = new ServerSocket(SERVER_PORT);

                while (!shutdown)
                {
                    Socket socket = serverSocket.accept();

                    InputStream inputStream = socket.getInputStream();
                    BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));

                    OutputStream outputStream = socket.getOutputStream();
                    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outputStream));

                    String readLine = br.readLine();
                    //System.out.println("Server read from client: " + readLine);

                    bw.write("Server saying hello to client");
                    bw.newLine();
                    bw.flush();

                    socket.close();

                    totalServerConnections++;
                    if (totalServerConnections % 10000 == 0)
                    {
                        System.out.println("totalServerConnections=" + totalServerConnections);
                    }
                }
            }
            catch (Exception e)
            {
                if (!shutdown)
                {
                    e.printStackTrace();
                }
            }
        }

        public void shutdown()
        {
            shutdown = true;
            try
            {
                serverSocket.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
}
…下面的例外情况有时会发生,因为我们正试图 重新打开尚未完全关闭的同一套接字错误: java.io.IOException:连接重置

你的分析不正确。这不是原因。套接字是全新的。连接是全新的。如果你得到了“连接重置”,那是因为服务器软件选择重置连接。在这方面,除了调查原因,以及在最坏的睡眠和重试情况下,你无法做任何事情

正如其他一些答案所暗示的那样,这与本地端口耗尽也没有关系。如果这是问题所在,您将得到一个
BindException


但是,您的客户端正在发送RST这一事实非常奇怪。您是否正在调用上面未显示的套接字API?

添加到@Erik的答案中,当您执行
新建套接字(IP,23)时
您每次都使用不同的本地端口打开不同的连接。您没有重复使用相同的连接。您必须发布更多的Wireshark跟踪,显示在包含数据包后发生的情况。再次查看后,我发现客户端正在向服务器发送RST。您收到的错误是否出现在se中服务器还是客户端?错误出现在客户端(TCP连接的发起方)@Erik,我更正了键入的错误代码(我将保留字static添加到了正确的位置)。您是否在短时间内创建了大量到服务器的连接?例如,在1或2分钟内创建了数千个连接?谢谢,但我们已经考虑过这一点,就像ti提到的那样,这是我们唯一的选择。如果您必须这样监视TCP内部,那么您就做错了。
public class TestTcpClientServer
{
    public static final int SERVER_PORT = 10111;

    public static void main(String[] args) throws Exception
    {
        Server server = new Server();
        server.start();

        Thread.sleep(500);

        Client client = new Client();
        client.start();

        System.out.println("Press enter to shutdown...");

        System.in.read();

        client.shutdown();
        client.join();
        server.shutdown();
        server.join();

        System.out.println("Done.");
    }

    public static class Client extends Thread
    {
        private volatile boolean shutdown = false;

        public void run()
        {
            try
            {
                int totalClientConnections = 0;

                while (!shutdown)
                {
                    Socket socket = new Socket("localhost", SERVER_PORT);

                    InputStream inputStream = socket.getInputStream();
                    BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));

                    OutputStream outputStream = socket.getOutputStream();
                    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outputStream));

                    bw.write("Client saying hello to server");
                    bw.newLine();
                    bw.flush();

                    String readLine = br.readLine();
                    //System.out.println("Client read from server: " + readLine);

                    System.out.println("Socket local port: " + socket.getLocalPort());

                    socket.close();

                    totalClientConnections++;
                    if (totalClientConnections % 10000 == 0)
                    {
                        System.out.println("totalClientConnections=" + totalClientConnections);
                    }

                    Thread.sleep(1000);
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }

        public void shutdown()
        {
            shutdown = true;
        }
    }

    public static class Server extends Thread
    {
        private volatile boolean shutdown = false;
        private ServerSocket serverSocket = null;

        public void run()
        {
            try
            {
                int totalServerConnections = 0;

                serverSocket = new ServerSocket(SERVER_PORT);

                while (!shutdown)
                {
                    Socket socket = serverSocket.accept();

                    InputStream inputStream = socket.getInputStream();
                    BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));

                    OutputStream outputStream = socket.getOutputStream();
                    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outputStream));

                    String readLine = br.readLine();
                    //System.out.println("Server read from client: " + readLine);

                    bw.write("Server saying hello to client");
                    bw.newLine();
                    bw.flush();

                    socket.close();

                    totalServerConnections++;
                    if (totalServerConnections % 10000 == 0)
                    {
                        System.out.println("totalServerConnections=" + totalServerConnections);
                    }
                }
            }
            catch (Exception e)
            {
                if (!shutdown)
                {
                    e.printStackTrace();
                }
            }
        }

        public void shutdown()
        {
            shutdown = true;
            try
            {
                serverSocket.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
}