tcp 服务端FIN_WAIT_2 状态下,客户端操作的抛错实验


import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
//客户端

public class Client {
  //private static String text="您好";

  public static void main(String[] args) {
     //Connection reset 连接被重置
    try{
    //创建套接字的连接对象
    Socket socket = new Socket("127.0.0.1",9090);
    OutputStream os = socket.getOutputStream();
    InputStream inputStream = socket.getInputStream();
    OutputStreamWriter osw = new OutputStreamWriter(os);
    BufferedWriter bdw = new BufferedWriter(osw);
    //
    String text="12\n";  //断点
    bdw.write(text, 0, text.length());
    bdw.flush();
    byte[] b=new byte[1];
    int read = inputStream.read(b);  // 代码1
   

    System.out.println("client");
//    bdw.close();
    }catch(Exception e){
      e.printStackTrace();
    }finally {
        System.out.println("server close");

    }
  }

}



client执行到断点处后,杀掉server进程。 这个时候操作系统会 自动帮你发送 tcp fin 命令。 这个是让人难以理解的。

通过 查看端口状态可知 服务端处于 FIN_WAIT_2 ,客户端处于CLOSE_WAIT  ,同时可知 [连接和进程是独立的]

 (更多 tcp 状态转移知识 可查看 http://blog.csdn.net/fei33423/article/details/50889385)

➜  ~ netstat -an | grep 127.0.0.1
tcp4       0      0  127.0.0.1.9090         127.0.0.1.49171        FIN_WAIT_2
tcp4       0      0  127.0.0.1.49171        127.0.0.1.9090         CLOSE_WAIT

第一个write 不报错,这个是很让人匪夷所思的。 通过抓包可知,服务端返回 rst ( tcp rst 标记位)

      rst是操作系统 tcp协议栈自动发送的

并且可以看到端口消失了。

说明客户端通过rst指令可以从close_wait进入到close状态.

服务端可以从fin_wait_2状态 直接走到close状态.(不排除,抛exception后, 进程被关闭了客户端发送fin)


 ➜  ~ netstat -an | grep 127.0.0.1


代码1 处会抛异常。

java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(SocketInputStream.java:196)
    at java.net.SocketInputStream.read(SocketInputStream.java:122)
    at java.net.SocketInputStream.read(SocketInputStream.java:108)
    at com.alibaba.rocketmq.common.admin.Client.main(Client.java:28)


如果把代码1 替换未 下面代码。

第一个write 依然不报错

第二个write会报如下错误。


bdw.write(text, 0, text.length());
    bdw.flush();


java.net.SocketException: Broken pipe
    at java.net.SocketOutputStream.socketWrite0(Native Method)
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113)
    at java.net.SocketOutputStream.write(SocketOutputStream.java:159)
    at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
    at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
    at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295)
    at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
    at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
    at java.io.BufferedWriter.flush(BufferedWriter.java:254)
    at com.alibaba.rocketmq.common.admin.Client.main(Client.java:28)



public class server {

    public static void main(String[] args) {
        try {
            ServerSocket server = new ServerSocket(9090);
            System.out.println("server:等待客户端连接");
            Socket socket = server.accept();
            System.out.println(socket.getRemoteSocketAddress() + "连接上服务器");

            InputStream is = socket.getInputStream();
            byte[] b = new byte[1];
            while (true) {
                int read = is.read(b);
                if(read!=-1){
                        System.out.println("line:" + b[0]);
                }else{
                        System.out.println("-1");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("server close");
        }
    }

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值