Bat*_*tty 2 java sockets networking tcp
我通过套接字代码进行 tcp 通信,例如:
public void openConnection() throws Exception
{
socket = new Socket();
InetAddress iNet = InetAddress.getByName("server");
InetSocketAddress sock = new InetSocketAddress(iNet, Integer.parseInt(port));
socket.connect(sock, 0);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
Run Code Online (Sandbox Code Playgroud)
并发送方法为:
synchronized void send(String message)
{
try
{
out.println(message);
}
catch (Exception e)
{
throw new RuntimeException(this.getClass() + ": Error Sending Message: "
+ message, e);
}
}
Run Code Online (Sandbox Code Playgroud)
我从网页上读到,TCP/IP 不保证数据包的传递,它会重试,但如果网络太忙,数据包可能会被丢弃([链接])。1
在系统之间传输数据时可能会丢弃数据包,主要有两个原因:
TCP 旨在能够在网络上丢弃数据包时做出反应。当数据包成功传送到其目的地时,目的地系统将确认消息发送回源系统。如果在某个时间间隔内未收到此确认,则可能是因为目标系统从未收到过该数据包,或者是因为包含该确认的数据包本身已丢失。在任一情况下,如果源系统在给定时间内未收到确认,则源系统假定目标系统从未收到该消息并重新传输该消息。不难看出,如果网络性能差,首先丢包,这些重传报文增加的负载只会进一步增加网络的负载,这意味着更多的数据包将丢失。此行为可能会导致非常迅速地在网络上创建危急情况。
有什么办法可以检测到目的地是否成功接收到数据包,我不确定这out.println(message);会引发任何异常,因为这是非阻塞调用。它会将消息放入缓冲区并返回以让 TCP/IP 完成其工作。
有什么帮助吗?
TCP 旨在能够在网络上丢弃数据包时做出反应。
正如您的引述所说,TCP 旨在自动对您在本文中提到的事件做出反应。因此,您在此级别无需执行任何操作,因为这将由您正在使用的 TCP 实现(例如在操作系统中)处理。
TCP 有一些特性可以为您完成一些工作,但是您对它们的局限性感到怀疑是正确的(许多人认为 TCP 是一种有保证的交付协议,没有上下文)。
在 Linux 内核邮件列表(“ Re: Client 收到 TCP 数据包但没有 ACK ”)上有一个有趣的讨论。
在您的用例中,实际上,这意味着您应该将您的 TCP 连接视为一个数据流,在每个方向上(典型的错误是假设如果您从头开始发送 n 个字节,您将读取 n 个字节在另一端读取单个缓冲区),并处理可能的异常。
java.io.IOException正确处理s(特别是 中的子类java.net)将涵盖您描述的级别的错误情况:如果您遇到错误情况,请制定重试策略(取决于应用程序及其用户打算做什么)。也依赖超时(不要将套接字设置为永远阻塞)。
应用协议也可以设计成在接收命令或请求时发送它们自己的确认。
这是将职责分配给不同层的问题。TCP 堆栈实现将处理您提到的丢包问题,并在无法自行修复时抛出错误/异常。它的职责是与远程 TCP 堆栈进行通信。由于在大多数情况下您希望您的应用程序与远程应用程序通信,因此需要额外的确认。通常,需要设计应用程序协议来处理这些情况。(在某些情况下,您可以向上移动多个层,具体取决于哪个实体负责处理请求/命令。)