繁体   English   中英

Java中可靠的TCP / IP

[英]Reliable TCP/IP in Java

有没有办法在java.net中使用Java TCP / IP库进行可靠的通信(发送者得知它发送的消息已被接收者接收)。*? 我知道TCP over UDP的一个优点是它的可靠性。 然而,我无法在下面的实验中得到这样的保证:

我创建了两个类:

1)echo server =>总是发回它收到的数据。

2)cli​​ent =>定期向echo服务器发送“Hello world”消息。

它们在不同的计算机上运行(并且工作得很好)。 在执行过程中,我断开了网络连接(拔掉了LAN电缆)。 断开连接后,服务器仍会等待数据,直到几秒钟过去(最终引发异常)。 同样,客户端也会继续发送数据,直到几秒钟过去(引发异常)。

问题是, objectOutputStream.writeObject(message)不保证objectOutputStream.writeObject(message)的传递状态(我希望它阻止线程,继续重发数据直到传递)。 或者至少我得到消息,哪些消息丢失了。

服务器代码:

import java.net.*;
import java.io.*;

import java.io.Serializable;

public class SimpleServer {
    public static void main(String args[]) {
        try {
            ServerSocket serverSocket = new ServerSocket(2002);
            Socket socket = new Socket();
            socket = serverSocket.accept();
            InputStream inputStream = socket.getInputStream();
            ObjectInputStream objectInputStream = new ObjectInputStream(
                    inputStream);

            while (true) {
                try {
                    String message = (String) objectInputStream.readObject();
                    System.out.println(message);
                    Thread.sleep(1000);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

客户代码:

import java.net.*;
import java.io.*;

public class SimpleClient {
    public static void main(String args[]) {
        try {
            String serverIpAddress = "localhost"; //change this

            Socket socket = new Socket(serverIpAddress, 2002);
            OutputStream outputStream = socket.getOutputStream();
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(
                    outputStream);

            while (true) {
                String message = "Hello world!";
                objectOutputStream.writeObject(message);

                System.out.println(message);
                Thread.sleep(1000);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

如果您需要知道哪些消息已到达对等应用程序,则对等应用程序必须发送确认。

如果你想要这种级别的保证,听起来你真的想要JMS。 这不仅可以确保消息已经传递,而且还可以正确处理。 也就是说,如果因为一个错误而被丢弃,那么没有必要提供非常可靠的交付。

您可以监控哪些消息正在等待以及哪些消费者落后。 观察生产者以查看它正在发送的消息,并在消息关闭时保存消息,并在重新启动时可用。 即使重新启动消费者,即可靠的交付。

TCP总是可靠的。 您不需要确认。 但是,要检查客户端是否已启动,您可能还需要使用带有确认的UDP流。 像PING一样? PONG! 系统。 可能也是您可以调整的TCP设置。

您的基本假设(以及对TCP的理解)在这里是错误的。 如果您拔下插头然后重新插入,则该消息很可能不会丢失。
它归结为您希望发件人等待多长时间。 一小时,一天? 如果你有一天超时,你会拔掉两天,然后仍然说“不起作用”。

因此,保证交付是“数据交付 - 或者您得到通知”。 在第二种情况下,您需要在应用程序级别上解决它。

您可以考虑使用SO_KEEPALIVE套接字选项,如果没有数据通过套接字传输2小时,将导致连接关闭。 但是,显然在许多情况下,这并不能提供应用程序通常所需的控制级别。

第二个问题是某些TCP / IP堆栈实现很差,并且在网络中断的情况下可能使您的服务器保持悬空开放连接。

因此,我建议在客户端和服务器之间添加应用程序级别的心跳,以确保双方仍然活着。 这还提供了切断连接的优点,例如,如果第三方客户端仍然活着但变得没有响应并因此停止发送心跳。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM