文档章节

Java I/O分析(jdk1.4之前)

ksfzhaohui
 ksfzhaohui
发布于 2012/12/14 14:11
字数 1235
阅读 62
收藏 0

#程序员薪资揭榜#你做程序员几年了?月薪多少?发量还在么?>>>

根据传输数据的方式这里把I/O流分为: 
1.基于磁盘操作的I/O接口:File 
2.基于网络操作的I/O接口:socket 

下面看一个典型的socket连接实例 

服务器端: 

public class ThreadSocketServer {
	/** 服务器端口 **/
	public static final int PORT = 8189;
	public static void main(String[] args) {
		int i = 1;
		try {
			ServerSocket s = new ServerSocket(PORT);
			System.out.println("Listening on port: " + PORT);
			while (true) {
				Socket incoming = s.accept();
				System.out.println("Spawning" + i);
				Runnable r = new ThreadedEchoHandler(incoming);
				Thread t = new Thread(r);
				t.start();
				i++;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

class ThreadedEchoHandler implements Runnable {
	private Socket incoming;
	public ThreadedEchoHandler(Socket i) {
		incoming = i;
	}
	@Override
	public void run() {
		try {
			try {
				OutputStream outStream = incoming.getOutputStream();
				PrintWriter out = new PrintWriter(outStream, true);
				out.println("Hello!");

			} finally {
				incoming.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
客户端: 

public class SocketClient {
	/** 客户端尝试连接的次数 **/
	public static final int CONNECT_UNM = 5000;
	/** 服务器端IP **/
	public static final String SERVER_IP = "127.0.0.1";
	public static void main(String[] args) {
		for (int i = 0; i < CONNECT_UNM; i++) {
			final int temp=i+1;
			new Thread(new Runnable() {
				@Override
				public void run() {
					Socket s = null;
					try {
						s = new Socket(SERVER_IP, ThreadSocketServer.PORT);
						System.out.println("第" + temp + "尝试连接--分配的本地端口:"
								+ s.getLocalPort());
						InputStream inStream = s.getInputStream();
						Scanner in = new Scanner(inStream);
						System.out.println(in.nextLine());
					} catch (Exception e) {
						e.printStackTrace();
					} finally {
						try {
							s.close();
						} catch (IOException e) {
						}
					}
				}
			}).start();
		
			try {
				Thread.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
		}
	}
}
从上面的例子中我们了解了以下几个关键点: 
1.连接->传输数据->关闭连接  是一个短连接的实例 

2.在客户端我们指定了一个连接数5000,当我们在本地的xp下进行测试时,当连接达到3970左右时,异常java.net.BindException: Address already in use: connect 
原因:在Java网络编程(一)中我们了解到:动态端口的分配范围为 1024-5000 ,也就是说默认情况下,客户端最多可以同时发起3977 个Socket 连接。有人会问我们不是在每次连接的时候都关闭了连接,应该会释放掉可用的端口啊? 
备注:关闭TCP连接 
我们要知道当我们关闭socket的时候我们要知道TCP连接并不是马上就能关闭。TCP协议有一个优雅的关闭(graceful close)机制,以保证应用程序在关闭连接时不必担心正在传输的数据会丢失。 
TCP还是使用了包括Time-Wait状态在内的多种机制对其进行防范。Time-Wait状态用于保证每个TCP连接都在一段平静时间内结束,这期间不会有数据发送。平静时间的长度应该等于分组报文在网络上存留的最长时间的两倍。因此,当一个连接完全结束(即套接字数据结构离开Time-Wait状态并被删除),并为同样一对地址上的新连接清理道路后,就不会再有旧实例发送的消息还存留在网络中。实际上,平静时间的长度要依赖于具体实现,因为没有机制能真正限制分组报文在网络上能够延迟的时间。通常使用的时间范围是4分钟减到30秒,或更短。 
Time-Wait状态最重要的作用是,只要底层套接字数据结构还存在,就不允许在相同的本地端口上关联其他套接字。尤其是试图使用该端口创建新的Socket实例时,将抛出IOException异常。 
所以在最短的30s内我们已经执完了我们的循环,最后导致客户端的动态端口不可用。 

3.阻塞与非阻塞 
阻塞与非阻塞主要是从 CPU 的消耗上来说的,阻塞就是 CPU 停下来等待一个慢的操作完成 CPU 才接着完成其它的事。非阻塞就是在这个慢的操作在执行时 CPU 去干其它别的事,等这个慢的操作完成时,CPU 再接着完成后续的操作。虽然表面上看非阻塞的方式可以明显的提高 CPU 的利用率,但是也带了另外一种后果就是系统的线程切换增加。增加的 CPU 使用时间能不能补偿系统的切换成本需要好好评估。 

我们知道在jdk1.4之前只有阻塞I/O,如果我们所有客户端的连接都放在一个线程中,这样的话,很容易造成一个用户出现问题(I/O阻塞)其他用户受到影响。所有一种常用的方式就是:在服务器端为每个到来的客户端都开通了一个线程,这样的话出现阻塞时只是一个线程阻塞而不会影响其它线程工作,还有为了减少系统线程的开销,采用线程池的办法来减少线程创建和回收的成本。但是这样的话也存在问题:系统的线程切换增加。 

针对以上的问题在jdk1.4以后提供了一个新的概念:nio,有效解决了多线程服务器存在的线程开销问题……………..待续

© 著作权归作者所有

ksfzhaohui

ksfzhaohui

粉丝 426
博文 167
码字总数 261352
作品 3
南京
高级程序员
私信 提问
加载中

评论(0)

Java BIO、NIO、AIO 原理

先来个例子理解一下概念,以银行取款为例: 同步 : 自己亲自出马持银行卡到银行取钱(使用同步IO时,Java自己处理IO读写)。 异步 : 委托一小弟拿银行卡到银行取钱,然后给你(使用异步IO时...

osc_i2b7a3j0
2018/01/06
19
0
Java NIO原理 图文分析及代码实现

Java NIO原理图文分析及代码实现 前言: 最近在分析hadoop的RPC(Remote Procedure Call Protocol ,远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术...

囚兔
2015/04/29
361
1
Java NIO原理图文分析及代码实现

前言: 最近在分析hadoop的RPC(Remote Procedure Call Protocol ,远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。可以参考:http://baik...

SunnyWu
2014/11/05
651
1
Tomcat的BIO、NIO、APR模式对比与性能测试结果

11.11活动当天,服务器负载过大,导致部分页面出现了不可访问的状态、那后来就要求调优了,下面是tomcat bio、nio、apr模式以及后来自己测试的一些性能结果。 原理方面的资料都是从网上找的,...

DemonsI
2019/02/15
231
0
Java NIO 机制分析(一) Java IO的演进

一、引言 Java1.4之前的早期版本,Java对I/O的支持并不完善,开发人员再开发高性能I/O程序的时候,会面临一些巨大的挑战和困难,主要有以下一些问题: (1)没有数据缓冲区,I/O性能存在问题...

宸明
2018/04/20
115
0

没有更多内容

加载失败,请刷新页面

加载更多

Discourse 如何在首页中显示 Box 的子分类

如下图, 如何在 Discourse 中显示子分类。 discourse-sub-col-01 1207×872 147 KB 你可以在分类的设定中进行设置,这个设定需要在上级目录中设置。 discourse-sub-col-02 556×656 76.3 KB...

honeymoose
17分钟前
27
0
OSChina 周六乱弹 —— 妈妈快看,外面有只人类

Osc乱弹歌单(2020)请戳(这里) 【今日歌曲】 @薛定谔的兄弟 :分享洛神有语创建的歌单「我喜欢的音乐」: 《1万年の时を越えて》- 上松範康 手机党少年们想听歌,请使劲儿戳(这里) @火眼...

小小编辑
23分钟前
27
0
git-Linux客户端使用

下载test代码 git pull https://gitee.com/yunmhs/test.git 上传test代码 git add . 将新更新的文件更新至本地git仓库( . 代表当前目录所有 ) git commit -m "Dockerfile Images update huan......

huanke
24分钟前
26
0
静态方法和类方法之间的区别 - Difference between staticmethod and classmethod

问题: 用@staticmethod装饰的函数和用@staticmethod装饰的函数有@staticmethod @classmethod ? 解决方案: 参考一: https://stackoom.com/question/ZP7/静态方法和类方法之间的区别 参考二...

javail
24分钟前
13
0
垃圾收集器与内存分配策略

对象已死? 垃圾标记算法 1.引用计数算法 C++智能指针、Python 2.可达性分析算法 JavaGC Roots的根对象作为起始节点,通过引用链到某个对象不可达时,证明此对象不可能再被使用。 强引用:...

LoSingSang
昨天
27
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部