Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
首次写入远程关闭的套接字不会触发异常,可以吗?JAVA_Java_Sockets_Exception - Fatal编程技术网

首次写入远程关闭的套接字不会触发异常,可以吗?JAVA

首次写入远程关闭的套接字不会触发异常,可以吗?JAVA,java,sockets,exception,Java,Sockets,Exception,我在任何地方都找不到这个问题令人满意的答案。请了解内部结构的人解释一下 我编写了一个简单的客户机/服务器来演示这个问题。服务器读取一行文本,然后关闭套接字。客户端写入一行文本,等待10秒,然后再写入两行文本。第二次写入(10秒后)失败,但第一次写入始终成功 为什么BufferedWriter不能在第一次写入时引发异常?毕竟,插座在很长一段时间之前是常闭的。代码还在第一次写入之前读取套接字,返回-1表示输入端已经检测到套接字关闭。为什么输出端不能也知道这一点 public class Serv

我在任何地方都找不到这个问题令人满意的答案。请了解内部结构的人解释一下

我编写了一个简单的客户机/服务器来演示这个问题。服务器读取一行文本,然后关闭套接字。客户端写入一行文本,等待10秒,然后再写入两行文本。第二次写入(10秒后)失败,但第一次写入始终成功

为什么BufferedWriter不能在第一次写入时引发异常?毕竟,插座在很长一段时间之前是常闭的。代码还在第一次写入之前读取套接字,返回-1表示输入端已经检测到套接字关闭。为什么输出端不能也知道这一点

  public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(9000);
        Socket s = ss.accept();
        BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
        System.out.println(in.readLine());
        s.close();
        System.out.println("Socket closed");
    }
  }

  public class Client {
    public static void main(String[] args) throws IOException, InterruptedException {
        Socket s = new Socket("localhost", 9000);
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        out.write("Hello, World!\n"); out.flush();
        Thread.sleep(10000);
        System.out.println("Read from socket returns: " + s.getInputStream().read());
        out.write("First write\n"); out.flush();
        System.out.println("First write succeeded without detecting socket closed");
        out.write("Second write\n"); out.flush();
        System.out.println("Second write succeeded without detecting socket closed");
    }
  }

远程关闭与远程关闭输出无法区分。在这两种情况下,该端都会收到FIN,这意味着对等方已停止发送。没有迹象表明他已停止接收,即使事实上他已关闭输入。因此,发送方可以检测的唯一方法是在发送时获取RST,根据定义,这不会发生在第一次发送时,除非发送的数据可能大于套接字发送缓冲区。

我们在一个项目中研究了这一点。我的意见是,或多或少地保证TCP/IP套接字可以做到这一点

IP协议的目的是尽可能做好路由数据包的工作。只有在写入/传递失败后,您才会知道另一端的连接已断开。记住,互联网的设计初衷是具有弹性的,可以尝试不同的途径等来传递信息

不同的网络和数据链路传输可能会有不同的工作方式。很久以前,我不得不在tcp/ip上做一个会话层,这个问题听起来非常熟悉


似乎您可以在主发送之前发送几个测试字节来解决这个问题

程序关闭了套接字并不意味着操作系统已经关闭了它。在客户端从底层系统接收到端口消失的响应之前,它假定一切正常。这就是为什么我们有协议和超时。你是对的,我把等待时间改为5分钟,第一次写入抛出异常。所以这可能是某种超时,尽管有正常的关闭顺序;这一定是操作系统处理套接字的方式。实际上,这回答了我的问题:这解释了我的问题。我不明白为什么在服务器关闭的连接上写入成功。我的解决方法是逐个写入字节。如果服务器关闭连接,写入第二个字节将失败。谢谢