Java socket中关闭IO流后,发生什么事?(以关闭输出流为例)
声明:该博文以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流后,发生什么事?(以关闭输出流为例)的更多相关文章
- Android—Socket中关闭IO流后导致Socket关闭不能再收发数据的解决办法
以Socket发送数据为例: 发送数据时候要声明:DataOutputStream os = new DataOutputStream(socket.getOutputStream()); 最近开发遇 ...
- Java中的IO流(二)
上一篇<Java中的IO流(一)>把学习IO流的字符流作了一下记录,本篇把字节流记录一下. 一,Java中的字节流 Java中的字节流的操作方式与字符流的操作方式大致相同,连方法名都是类似 ...
- Java中的IO流之输出流|乐字节
大家好,乐字节小乐又来了.上一篇给大家带来的是:Java中的IO流之输入流|乐字节,本文将继续讲述IO流之输出流. 一.输出流 1.抽象类:OutputStream 和 Writer Output ...
- Java中的IO流(一)
一,IO流的分类 A,按照操作的对象不同可分为字节流与字符流 B,按照流的方向不同可分为输入(指从外部存储设备拿文件到内存)流也叫读与输出(指从内存把文件写入到外部存储设备)流也叫写 注:字节流可以操 ...
- Java中的IO流,Input和Output的用法,字节流和字符流的区别
Java中的IO流:就是内存与设备之间的输入和输出操作就成为IO操作,也就是IO流.内存中的数据持久化到设备上-------->输出(Output).把 硬盘上的数据读取到内存中,这种操作 成为 ...
- Java中的IO流(五)
上一篇<Java中的IO流(四)>记录了一下Properties类,此类不属于IO流,它属于集合框架.接下来说一下IO流中的其它流 一,打印流PrintStream PrintStream ...
- Java中的IO流 - 入门篇
前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的IO流-入门篇>,希望对大家有帮助,谢谢 由于Java的IO类有很多,这就导致我刚开始学的时候,感觉很乱,每次用到都是上网搜,结果 ...
- Java中的IO流总结
Java中的IO流总结 1. 流的继承关系,以及字节流和字符流. 2. 节点流FileOutputStream和FileInputStream和处理流BufferedInputStream和Buffe ...
- Java中的IO流大体介绍
由于Java中的IO流是在是知识点繁多,所以我大约花了1周的时间将其整理起来.但是整理起来后并不是将完事了,我还是要分字节流和字符流来讲述.然后字节流和字符流中还有是否带有缓冲流. 讲述完IO流后我将 ...
随机推荐
- Ubuntu中搭建Nginx+PHP环境最简单的方法
先安装: sudo apt-get install nginx php5-fpm 然后编辑配置文件: sudo gedit /etc/nginx/site-available/default 找到lo ...
- wordpress自定义数据库出错页面
wordpress数据连接出错时,会有一个空白页面,有一行字:数据连接错误.这样当然不美观,好在这个页面是可以自定义的. 在/wp-content/目录下创建'db-error.php'文件,当数据库 ...
- mybatis 中#{}与${}的区别 (面试题)
MyBatis/Ibatis中#和$的区别 1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号. 如:order by #user_id#,如果传入的值是111,那么解析成sql时的 ...
- Android Studio 快捷键使用
最近开始全面转向Android Studio开发了,经常要去查快捷键,索性汇总下,自己方便查找 IDE 按键 说明 F1 帮助 Alt(Option)+F1 查找文件所在目录位置 Alt(Opt ...
- SQL查询的几种方式
/* 左连接 left join 或者 left outer join */ /* 左连接 Table_A表数据全部显示,Table_B根据条件匹配Table_A 匹配上显示,否则显示NULL */ ...
- zepto-创建dom
在使用zepto时,为了使得ajax请求回来的数据添加到页面上之后,不至于失去所绑定的事件. 我一般会采用$()创建dom元素节点,然后添加所需要的class和html等等一系列的样式,最基本的是$( ...
- Solr分页与高亮(使用SolrNet实现)
Solr分页与高亮(使用SolrNet实现) 本节我们使用Asp.net MVC实现Solr客户端查询,建议使用SolrNet这个客户端,开源地址在:https://github.com/mausch ...
- VMware网络配置 - 三种网络模式简介
安装好虚拟机以后,在网络连接里面可以看到多了两块网卡: 其 中VMnet1是虚拟机Host-only模式的网络接口,VMnet8是NAT模式的网络接口,这些后面会详细介绍 选择虚拟机网络模 式方法如下 ...
- 一些html页面资料
一下没有什么重要的,只是我平时积累的一些页面,紧急时或许会有用,相信过一段时间去东宇(公司分公司)了,这些资料页带不走,还不如留在博客里,趁组长级别们开会去了,他们已经开了一个点啦!我的组长去东宇查看 ...
- 深度学习笔记(三 )Constitutional Neural Networks
一. 预备知识 包括 Linear Regression, Logistic Regression和 Multi-Layer Neural Network.参考 http://ufldl.stanfo ...