声明:该博文以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:

Java socket中关闭IO流后,发生什么事?(以关闭输出流为例)

Java socket中关闭IO流后,发生什么事?(以关闭输出流为例)的更多相关文章

  1. Android—Socket中关闭IO流后导致Socket关闭不能再收发数据的解决办法

    以Socket发送数据为例: 发送数据时候要声明:DataOutputStream os = new DataOutputStream(socket.getOutputStream()); 最近开发遇 ...

  2. Java中的IO流(二)

    上一篇<Java中的IO流(一)>把学习IO流的字符流作了一下记录,本篇把字节流记录一下. 一,Java中的字节流 Java中的字节流的操作方式与字符流的操作方式大致相同,连方法名都是类似 ...

  3. Java中的IO流之输出流|乐字节

    大家好,乐字节小乐又来了.上一篇给大家带来的是:Java中的IO流之输入流|乐字节,本文将继续讲述IO流之输出流.   一.输出流 1.抽象类:OutputStream 和 Writer Output ...

  4. Java中的IO流(一)

    一,IO流的分类 A,按照操作的对象不同可分为字节流与字符流 B,按照流的方向不同可分为输入(指从外部存储设备拿文件到内存)流也叫读与输出(指从内存把文件写入到外部存储设备)流也叫写 注:字节流可以操 ...

  5. Java中的IO流,Input和Output的用法,字节流和字符流的区别

    Java中的IO流:就是内存与设备之间的输入和输出操作就成为IO操作,也就是IO流.内存中的数据持久化到设备上-------->输出(Output).把 硬盘上的数据读取到内存中,这种操作 成为 ...

  6. Java中的IO流(五)

    上一篇<Java中的IO流(四)>记录了一下Properties类,此类不属于IO流,它属于集合框架.接下来说一下IO流中的其它流 一,打印流PrintStream PrintStream ...

  7. Java中的IO流 - 入门篇

    前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的IO流-入门篇>,希望对大家有帮助,谢谢 由于Java的IO类有很多,这就导致我刚开始学的时候,感觉很乱,每次用到都是上网搜,结果 ...

  8. Java中的IO流总结

    Java中的IO流总结 1. 流的继承关系,以及字节流和字符流. 2. 节点流FileOutputStream和FileInputStream和处理流BufferedInputStream和Buffe ...

  9. Java中的IO流大体介绍

    由于Java中的IO流是在是知识点繁多,所以我大约花了1周的时间将其整理起来.但是整理起来后并不是将完事了,我还是要分字节流和字符流来讲述.然后字节流和字符流中还有是否带有缓冲流. 讲述完IO流后我将 ...

随机推荐

  1. 关于0x000000c2问题解决方法

    首先大家要用进入PE系统,按照我说的顺序做就可以解决了! 1,进入PE后找到系统盘,默认一般为C盘-->进入WINDOWS文件夹-->进入system32文件夹-->找到regedt ...

  2. PHP函数库(other)

    PHP函数库(other) Session函数: session_abort — Discard session array changes and finish session session_ab ...

  3. 当多个工程互相引用时,若有serverlet工程,提示java.lang.NoClassDefFoundError错误

    serverlet工程和其他的工程引用有所不同,直接在buildpath中添加引用的工程会报NoClassDefFoundError错误错误, 需要在properties-depoyment asse ...

  4. Error:(12) No resource identifier found for attribute 'titles' in package 'com.itheima52.mobilesafe5

    http://stackoverflow.com/questions/5819369/error-no-resource-identifier-found-for-attribute-adsize-i ...

  5. flex mxmlc 手动编译项目

    首先: 1.下载flex的sdk,如果你电脑有装flash builder,它自带了一份,位于安装目录的sdks目录下. 备注:(sdk依赖java的jre) 2.配置mxmlc的java运行环境jr ...

  6. window对象;document对象;

    window对象: DOM:文档对象模型 --树模型文档:标签文档,对象:文档中每个元素对象,模型:抽象化的东西 一:window: 属性(值或者子对象):opener:打开当前窗口的源窗口,如果当前 ...

  7. 将真彩色转换成增强色的方法(即RGB32位或RGB24位颜色转换成RGB16位颜色的函数)

    今天由于程序需要,需要将真彩色转换成增强色进行颜色匹配,上网搜了一下没搜到相应函数,于是研究了一下RGB16位的增强色,写了这个函数: public static int RGB16(int argb ...

  8. nrf51822裸机教程-UART

    art硬件模块通常都有内置的硬件接收buff,比如51822的硬件uart模块图如下 因为通常接收到uart数据时都会做一些处理.比如保存到数据,或者对数据做一些判断之类的. 如果uart的波特率设置 ...

  9. FastReport的交叉表实际使用的一个例子

    计算发行-->定义份数月表(打开)出现 PosFraisPaysInput选择时间段后,点击“打印”.这个设计表格,就是交叉表. 交叉表的特点是:数据库是一条一条并列的但是出来的结果却是:横向是 ...

  10. asp.net实现关闭当前网页

    asp.net实现关闭当前网页功能:Response.Write("<script>window.close();</script>");// 会弹出询问是 ...