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");
}
}
}