博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java socket中关闭IO流后,发生什么事?(以关闭输出流为例)
阅读量:6006 次
发布时间:2019-06-20

本文共 6432 字,大约阅读时间需要 21 分钟。

声明:该博文以socket中,关闭输出流为例进行说明。

 

为了方便讲解,我们把DataOutputstream dout = new DataOutputStream(new BufferedOutputStream(mySocket.getOutputStream()));中的dout做为Socket输出流的代言。同样的,din是输入流的代言。

可以造成dout被关闭的操作有:

1、调用dout.close();或din.close();因为使用这种流关闭,会造成socket被关闭,所以输入输出流都将不可再用。

2、调用socket.close();

3、调用socket.shutdownOutputStream();单方面关闭dout,此时din还可正常使用。

 

以下,我将对socket中关闭输出流进行3个测试

输出流关闭测试一:socket关闭吗?
输出流关闭测试二:该流是否可以重新开启?
输出流关闭测试三:输出缓冲区里的数据是丢弃,还是发送?
测试结果如下:

测试一:dout.close();会造成socket被关闭,但socket.shutdownOutputStream()不会。

测试二:不可以,会抛出异常!

测试三:丢弃

微笑客户端程序:

package com.test2;import java.io.*;import java.net.*;/*** @ClassName: SocketTest* @Description: 测试Socket中,流关闭后,socket是否关闭?是否可重开流?输出缓存区的数据是发送出去,还是丢弃?* @author 慢跑学Android* @date 2011-11-12 上午11:15:21* */public class SocketTest {    Socket mySocket;    DataOutputStream dout;    public static void main(String[] args){        new SocketTest();    }        public SocketTest(){        // 输出流关闭的测试一:socket关闭吗?        test1();        // 输出流关闭测试二:该流是否可以重新开启?        test2();        // 输出流关闭测试三:输出缓冲区里的数据是丢弃,还是发送?        test3();    }    private void test1() {        // 输出流关闭的测试一:socket关闭吗?        System.out.println("\n****2种方式关闭输出流,Socket是否关闭?***\n");        try {            mySocket = new Socket("27.154.122.233",9999);        } catch (UnknownHostException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }                try {            dout = new DataOutputStream(new BufferedOutputStream(mySocket.getOutputStream()));            //下面这一句主要是用来证明socket确实处于开启状态            System.out.println("输出流刚打开,Socket是否关闭?" + mySocket.isClosed());            mySocket.shutdownOutput();            System.out.println("使用shutdownOutput关闭输出流,Socket是否关闭?" + mySocket.isClosed());            dout.close();            System.out.println("使用close关闭输出流,Socket是否关闭?" + mySocket.isClosed());        } catch (IOException e) {            e.printStackTrace();        }    }    private void test2() {        // 输出流关闭测试二:使用shutdownOutputStream后,输出流是否可以重新开启?        System.out.println("\n****使用shutdownOutputStream后,输出流是否可以重新开启?***\n");        try {            mySocket = new Socket("27.154.122.233",9999);        } catch (UnknownHostException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }                try {            dout = new DataOutputStream(new BufferedOutputStream(mySocket.getOutputStream()));            mySocket.shutdownOutput();            // 重开输出流            dout = new DataOutputStream(mySocket.getOutputStream());            dout.writeUTF("是否允许我重开?");            // 清空输出缓存,确保当dout通道没问题时,消息可以到达服务器            dout.flush();        } catch (IOException e) {            e.printStackTrace();        } finally {            try {                mySocket.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }        private void test3(){        // 输出流关闭测试三:输出缓冲区里的数据是丢弃,还是发送?        System.out.println("\n***输出缓冲区里的数据是丢弃,还是发送?****\n");        try {            mySocket = new Socket("27.154.122.233",9999);        } catch (UnknownHostException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }                try {            dout = new DataOutputStream(new BufferedOutputStream(mySocket.getOutputStream()));            dout.writeUTF("shutdownOutput后,数据发得得出去吗?");            mySocket.shutdownOutput();        } catch (IOException e) {            e.printStackTrace();        }    }}

 

微笑服务器端程序:

/**   * @Title: ServerSocketTest.java* @Package com.test1* @Description: TODO(该文件为”Socket中,流关闭后,发生什么事“的Sever测试端)* @author 慢跑学Android* @date 2011-11-12 上午11:31:05* @version V1.0   */package com.test1;import java.io.*;import java.net.*;public class ServerSocketTest extends Thread{    private ServerSocket myServerSocket;    private final int PORT = 9999;    public static void main(String[] args){        ServerSocketTest sst = new ServerSocketTest();        sst.start();    }        public ServerSocketTest(){        // 初始化一个ServeSocket端        try {            myServerSocket = new ServerSocket(PORT);        } catch (IOException e) {            e.printStackTrace();        }    }        public void run(){        while(true){            System.out.println("我是服务器,我在9999端口监听....");            try {                Socket socket = myServerSocket.accept();                DataInputStream din = new DataInputStream(new BufferedInputStream(socket.getInputStream()));                String msgIn = din.readUTF();                System.out.println(msgIn.trim());            } catch (IOException e) {                e.printStackTrace();            }        }    }}

说明一点:

在test3()中,因为dout = new DataOutputStream(newBufferedOutputStream(mySocket.getOutputStream()));使用了Buffered,所以在dout.writeUTF()方法后,如果没有使用dout.flush();数据会存在输出缓存中,不会发送出去的。

如果我们队dout的声明是,dout = new DataOutputStream(mySocket.getOutputStream());那么,数据会立即发送出去。(除非,对方没有调用read()来读取数据,且数据量极大,超过了对方的输入缓存。不过,此时dout.writeUTF();这里会堵塞。)

以下是程序运行后,客户端与服务器各自的控制台输出情况:

----------------------------------客户端--------------------------

java.net.SocketException: Socket output is shutdown

 at java.net.Socket.getOutputStream(Unknown Source)
 at com.test2.SocketTest.test2(SocketTest.java:66)
 at com.test2.SocketTest.<init>(SocketTest.java:22)
 at com.test2.SocketTest.main(SocketTest.java:15)

****2种方式关闭输出流,Socket是否关闭?***

输出流刚打开,Socket是否关闭?false

使用shutdownOutput关闭输出流,Socket是否关闭?false
使用close关闭输出流,Socket是否关闭?true

****使用shutdownOutputStream后,输出流是否可以重新开启?***

***输出缓冲区里的数据是丢弃,还是发送?****

 

---------------------------------服务器------------------------------

我是服务器,我在9999端口监听....

我是服务器,我在9999端口监听....
java.io.EOFException
 at java.io.DataInputStream.readUnsignedShort(Unknown Source)
 at java.io.DataInputStream.readUTF(Unknown Source)
 at java.io.DataInputStream.readUTF(Unknown Source)
 at com.test1.ServerSocketTest.run(ServerSocketTest.java:37)
java.io.EOFException
 at java.io.DataInputStream.readUnsignedShort(Unknown Source)
 at java.io.DataInputStream.readUTF(Unknown Source)
 at java.io.DataInputStream.readUTF(Unknown Source)
 at com.test1.ServerSocketTest.run(ServerSocketTest.java:37)
java.io.EOFException
 at java.io.DataInputStream.readUnsignedShort(Unknown Source)

我是服务器,我在9999端口监听....

 at java.io.DataInputStream.readUTF(Unknown Source)

 at java.io.DataInputStream.readUTF(Unknown Source)
 at com.test1.ServerSocketTest.run(ServerSocketTest.java:37)

 

Reference:

 

你可能感兴趣的文章
关于Server Sql 2008触发器的使用
查看>>
mac常见命令
查看>>
Redhat 系统相关调优参数注解
查看>>
nextus的使用
查看>>
Python自动化开发学习5-2-subprocess模块
查看>>
编程实现最小化窗口到桌面右下角图标的代码
查看>>
ELK stack实战之结合rsyslog分析系统日志(auth.log)
查看>>
网络管理工具与IT运维管理平台的差别
查看>>
五一期间安全回顾 木马威胁提升 移动设备数据泄漏受重视
查看>>
VDI序曲二十 桌面虚拟化和RemoteApp集成到SharePoint 2010里
查看>>
oracle里long类型的总结
查看>>
10种有用的CSS技巧
查看>>
服务端接口中的那些坑
查看>>
MySql like 查询 变向写法(不用like 完成like查询)
查看>>
Struts 笔记
查看>>
《C++面向对象高效编程(第2版)》——2.2 对象接口的重要性
查看>>
五个 ping 工具的使用实例
查看>>
在Linux系统下玩《炉石传说:魔兽英雄传》
查看>>
阿里数据库内核月报:2016年01月
查看>>
Samba 系列(七):在 Samba AD DC 服务器上创建共享目录并映射到 Windows/Linux 客户...
查看>>