当前位置: 首页 > news >正文

(转)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()不会。

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

测试三:丢弃

微笑客户端程序:

 

01.package com.test2;  
02.import java.io.*;  
03.import java.net.*;  
04./** 
05.* @ClassName: SocketTest 
06.* @Description: 测试Socket中,流关闭后,socket是否关闭?是否可重开流?输出缓存区的数据是发送出去,还是丢弃? 
07.* @author 慢跑学Android 
08.* @date 2011-11-12 上午11:15:21 
09.*  
10.*/  
11.public class SocketTest {  
12.    Socket mySocket;  
13.    DataOutputStream dout;  
14.    public static void main(String[] args){  
15.        new SocketTest();  
16.    }  
17.      
18.    public SocketTest(){  
19.        // 输出流关闭的测试一:socket关闭吗?   
20.        test1();  
21.        // 输出流关闭测试二:该流是否可以重新开启?   
22.        test2();  
23.        // 输出流关闭测试三:输出缓冲区里的数据是丢弃,还是发送?   
24.        test3();  
25.    }  
26.  
27.    private void test1() {  
28.        // 输出流关闭的测试一:socket关闭吗?   
29.        System.out.println("\n****2种方式关闭输出流,Socket是否关闭?***\n");  
30.        try {  
31.            mySocket = new Socket("27.154.122.233",9999);  
32.        } catch (UnknownHostException e) {  
33.            e.printStackTrace();  
34.        } catch (IOException e) {  
35.            e.printStackTrace();  
36.        }  
37.          
38.        try {  
39.            dout = new DataOutputStream(new BufferedOutputStream(mySocket.getOutputStream()));  
40.            //下面这一句主要是用来证明socket确实处于开启状态   
41.            System.out.println("输出流刚打开,Socket是否关闭?" + mySocket.isClosed());  
42.            mySocket.shutdownOutput();  
43.            System.out.println("使用shutdownOutput关闭输出流,Socket是否关闭?" + mySocket.isClosed());  
44.            dout.close();  
45.            System.out.println("使用close关闭输出流,Socket是否关闭?" + mySocket.isClosed());  
46.        } catch (IOException e) {  
47.            e.printStackTrace();  
48.        }  
49.    }  
50.  
51.    private void test2() {  
52.        // 输出流关闭测试二:使用shutdownOutputStream后,输出流是否可以重新开启?   
53.        System.out.println("\n****使用shutdownOutputStream后,输出流是否可以重新开启?***\n");  
54.        try {  
55.            mySocket = new Socket("27.154.122.233",9999);  
56.        } catch (UnknownHostException e) {  
57.            e.printStackTrace();  
58.        } catch (IOException e) {  
59.            e.printStackTrace();  
60.        }  
61.          
62.        try {  
63.            dout = new DataOutputStream(new BufferedOutputStream(mySocket.getOutputStream()));  
64.            mySocket.shutdownOutput();  
65.            // 重开输出流   
66.            dout = new DataOutputStream(mySocket.getOutputStream());  
67.            dout.writeUTF("是否允许我重开?");  
68.            // 清空输出缓存,确保当dout通道没问题时,消息可以到达服务器   
69.            dout.flush();  
70.        } catch (IOException e) {  
71.            e.printStackTrace();  
72.        } finally {  
73.            try {  
74.                mySocket.close();  
75.            } catch (IOException e) {  
76.                e.printStackTrace();  
77.            }  
78.        }  
79.    }  
80.      
81.    private void test3(){  
82.        // 输出流关闭测试三:输出缓冲区里的数据是丢弃,还是发送?   
83.        System.out.println("\n***输出缓冲区里的数据是丢弃,还是发送?****\n");  
84.        try {  
85.            mySocket = new Socket("27.154.122.233",9999);  
86.        } catch (UnknownHostException e) {  
87.            e.printStackTrace();  
88.        } catch (IOException e) {  
89.            e.printStackTrace();  
90.        }  
91.          
92.        try {  
93.            dout = new DataOutputStream(new BufferedOutputStream(mySocket.getOutputStream()));  
94.            dout.writeUTF("shutdownOutput后,数据发得得出去吗?");  
95.            mySocket.shutdownOutput();  
96.        } catch (IOException e) {  
97.            e.printStackTrace();  
98.        }  
99.    }  
100.}  

 

 
微笑服务器端程序:

 

01./**    
02.* @Title: ServerSocketTest.java 
03.* @Package com.test1 
04.* @Description: TODO(该文件为”Socket中,流关闭后,发生什么事“的Sever测试端) 
05.* @author 慢跑学Android 
06.* @date 2011-11-12 上午11:31:05 
07.* @version V1.0    
08.*/  
09.package com.test1;  
10.  
11.import java.io.*;  
12.import java.net.*;  
13.  
14.public class ServerSocketTest extends Thread{  
15.    private ServerSocket myServerSocket;  
16.    private final int PORT = 9999;  
17.    public static void main(String[] args){  
18.        ServerSocketTest sst = new ServerSocketTest();  
19.        sst.start();  
20.    }  
21.      
22.    public ServerSocketTest(){  
23.        // 初始化一个ServeSocket端   
24.        try {  
25.            myServerSocket = new ServerSocket(PORT);  
26.        } catch (IOException e) {  
27.            e.printStackTrace();  
28.        }  
29.    }  
30.      
31.    public void run(){  
32.        while(true){  
33.            System.out.println("我是服务器,我在9999端口监听....");  
34.            try {  
35.                Socket socket = myServerSocket.accept();  
36.                DataInputStream din = new DataInputStream(new BufferedInputStream(socket.getInputStream()));  
37.                String msgIn = din.readUTF();  
38.                System.out.println(msgIn.trim());  
39.            } catch (IOException e) {  
40.                e.printStackTrace();  
41.            }  
42.        }  
43.    }  
44.}  

 

 

说明一点:

在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)

 

 

 

转载于:https://www.cnblogs.com/alex2520/archive/2013/01/17/2863901.html

相关文章:

  • Objective-C 学习笔记3 类的扩展(category)
  • IE 6解决背景透明比较好的方案,补充、
  • ThinkPHP邮件发送函数使用
  • MATLAB 笔记,关于Filter函数的功能和使用,求simple(冲激)和unit step(阶跃)响应...
  • pku3273 Monthly Expense
  • 【ZOJ月赛】【树形DP】【I.Destroy】
  • 概要设计与详细设计的区别
  • templates of angularjs
  • wp7的数据库并发异常
  • Jquery验证输入框只能输入数字
  • 一些视频教程网站推荐
  • 利用最新的开源软件构建日志管理系统
  • Ubuntu 恢复 ctrl+f
  • 程序员,你懂的.
  • HDOJ 1133 Buy the Ticket 简单解题报告
  • 3.7、@ResponseBody 和 @RestController
  • JSONP原理
  • Linux CTF 逆向入门
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • SQLServer之创建显式事务
  • uni-app项目数字滚动
  • 从PHP迁移至Golang - 基础篇
  • 后端_MYSQL
  • 《码出高效》学习笔记与书中错误记录
  • Java数据解析之JSON
  • ​七周四次课(5月9日)iptables filter表案例、iptables nat表应用
  • ###51单片机学习(1)-----单片机烧录软件的使用,以及如何建立一个工程项目
  • #android不同版本废弃api,新api。
  • #AngularJS#$sce.trustAsResourceUrl
  • #pragma once
  • #我与Java虚拟机的故事#连载03:面试过的百度,滴滴,快手都问了这些问题
  • $L^p$ 调和函数恒为零
  • (20)目标检测算法之YOLOv5计算预选框、详解anchor计算
  • (2020)Java后端开发----(面试题和笔试题)
  • (C#)获取字符编码的类
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • (十七)devops持续集成开发——使用jenkins流水线pipeline方式发布一个微服务项目
  • (学习日记)2024.01.19
  • (原+转)Ubuntu16.04软件中心闪退及wifi消失
  • (原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (轉貼) 2008 Altera 亞洲創新大賽 台灣學生成果傲視全球 [照片花絮] (SOC) (News)
  • ***通过什么方式***网吧
  • .Net Memory Profiler的使用举例
  • .NET MVC、 WebAPI、 WebService【ws】、NVVM、WCF、Remoting
  • .NET国产化改造探索(一)、VMware安装银河麒麟
  • .NET建议使用的大小写命名原则
  • ::前边啥也没有
  • @德人合科技——天锐绿盾 | 图纸加密软件有哪些功能呢?
  • [2669]2-2 Time类的定义
  • [APIO2015]巴厘岛的雕塑
  • [bbk5179]第66集 第7章 - 数据库的维护 03
  • [BZOJ 1040] 骑士
  • [HJ73 计算日期到天数转换]