您的位置:首页 > 理论基础 > 计算机网络

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

2016-03-14 22:23 459 查看
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");
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: