- 浏览: 81406 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
撼地神牛:
你这服务 ,还是多线程的啊! 真晕!
用java.nio.*进行网络编程 -
f_zongjian:
多行注释符:/*注释*/
mysql注释符 -
lixjluck:
这个不是原理和使用吧,误导。。。
Java NIO原理和使用 -
sunjilu05:
有没有办法在两台内网的机器之间通过第三方服务器的牵引,建立一个 ...
Java Socket编程 -
xombat:
关键是如果发生这样一种情况,问题就会很复杂:相邻两点之间是多条 ...
最短路径算法
转载:http://java.chinaitlab.com/net/522829.html
前言
因为打算用java编写异步通信的server和client程序,笔者便学习使用java.nio
开发包,其间遇到一些问题,上网却发现网上对它的应用描述的不是很多。所以,笔者不惜班门弄斧,做些简单的讨论,以便大家更进一步的讨论。
对相关类的简单介绍
java.nio.*, 据说它提供了一些更加底层的一些功能,如:类似windows环境下的
AsyncSocket类的异步操作的功能,能显著降低server端程序的线程管理开销。
因为大多数应用是建立在TCP之上,所以在此只说说SocketChannel,
ServerSocketChannel,Selector和ByteBuffer这几个类.前三个最终都源自channel类。而channel 类,可以理解为在具体I/O或文件对象之上抽象的一个操作对象,我们通过操作channel的读写达到对其对应的文件或I/O对象(包括socket)读写的目的。读写的内容在内存中放在ByteBuffer类提供的缓冲区。总而言之,channel作为一个桥梁,连接了I/O对象和内存中的ByteBuffer,实现了I/O的更高效的存取。
一个基于TCP的服务器端程序,必然有个侦听端和若干个通信端,它们在nio中由对应的ServerSocketChannel 和SocketChannel类来实现。为了达到异步I/O操作的目的,需要Selector类,它能检测到I/O对象的状态。
SocketChannel类是抽象类,通过调用它的静态函数open(),可生成一个
SocketChannel对象,该对象对应一个java.net.Socket,可通过SocketChannel.socket()获得,而其对应的Socket也可通过调用函数getChannel()得到已建立的相应SocketChannel。
SocketChannel与它的socket是一一对应的。SocketChannel的操作与Socket也很相似.
ServerSocketChannel也是通过调用它的静态函数open()生成的,只是它不能
直接调用bind()函数来绑定一个地址,需要它对应的ServerSocket来完成绑定工作,一般可按如下步骤做:
ServerSocketChannel ssc = new ServerSocketChannel.open();
ssc.socket().bind(InetSocketAddress(host,port));
罗嗦了半天,还是看看最简单的C/S实现吧,服务器提供了基本的回射(echo)功
能,其中提供了较详细的注释。
源码分析
1.服务器端:
////////////////////////
//AsyncServer.java
// by zztudou@163.com
////////////////////////
import java.nio.channels.SocketChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.spi.SelectorProvider;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Iterator;
import java.util.LinkedList;
import java.io.IOException;
class AsyncServer implements Runnable{
private ByteBuffer r_buff = ByteBuffer.allocate(1024);
private ByteBuffer w_buff = ByteBuffer.allocate(1024);
private static int port = 8848;
public AsyncServer(){
new Thread(this).start();
}
public void run(){
try{
//生成一个侦听端
ServerSocketChannel ssc = ServerSocketChannel.open();
//将侦听端设为异步方式
ssc.configureBlocking(false);
//生成一个信号监视器
Selector s = Selector.open();
//侦听端绑定到一个端口
ssc.socket().bind(new InetSocketAddress(port));
//设置侦听端所选的异步信号OP_ACCEPT
ssc.register(s,SelectionKey.OP_ACCEPT);
System.out.println("echo server has been set up ......");
while(true){
int n = s.select();
if (n == 0) {//没有指定的I/O事件发生
continue;
}
Iterator it = s.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey key = (SelectionKey) it.next();
if (key.isAcceptable()) {//侦听端信号触发
ServerSocketChannel server = (ServerSocketChannel) key.channel();
//接受一个新的连接
SocketChannel sc = server.accept();
sc.configureBlocking(false);
//设置该socket的异步信号OP_READ:当socket可读时,
//触发函数DealwithData();
sc.register(s,SelectionKey.OP_READ);
}
if (key.isReadable()) {//某socket可读信号
DealwithData(key);
}
it.remove();
}
}
}
catch(Exception e){
e.printStackTrace();
}
}
public void DealwithData(SelectionKey key) throws IOException{
int count;
//由key获取指定socketchannel的引用
SocketChannel sc = (SocketChannel)key.channel();
r_buff.clear();
//读取数据到r_buff
while((count = sc.read(r_buff))> 0)
;
//确保r_buff可读
r_buff.flip();
w_buff.clear();
//将r_buff内容拷入w_buff
w_buff.put(r_buff);
w_buff.flip();
//将数据返回给客户端
EchoToClient(sc);
w_buff.clear();
r_buff.clear();
}
public void EchoToClient(SocketChannel sc) throws IOException{
while(w_buff.hasRemaining())
sc.write(w_buff);
}
public static void main(String args[]){
if(args.length > 0){
port = Integer.parseInt(args[0]);
}
new AsyncServer();
}
}
在当前目录下运行:
javac AsynServer.java
后,若无编译出错,接下来可运行:
java AsynServer 或 java AsynServer ×××(端口号)
上述服务程序在运行时,可指定其侦听端口,否则程序会取8848为默认端口。
2.客户端的简单示例:
////////////////////////
//AsyncClient.java
// by zztudou@163.com
////////////////////////
import java.nio.channels.SocketChannel;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Selector;
import java.nio.channels.SelectionKey;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
class AsyncClient{
private SocketChannel sc;
private final int MAX_LENGTH = 1024;
private ByteBuffer r_buff = ByteBuffer.allocate(MAX_LENGTH);
private ByteBuffer w_buff = ByteBuffer.allocate(MAX_LENGTH);
private static String host ;
private static int port = 8848;
public AsyncClient(){
try {
InetSocketAddress addr = new InetSocketAddress(host,port);
//生成一个socketchannel
sc = SocketChannel.open();
//连接到server
sc.connect(addr);
while(!sc.finishConnect())
;
System.out.println("connection has been established!...");
while(true){
//回射消息
String echo;
try{
System.err.println("Enter msg you'd like to send: ");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//输入回射消息
echo = br.readLine();
//把回射消息放入w_buff中
w_buff.clear();
w_buff.put(echo.getBytes());
w_buff.flip();
}catch(IOException ioe){
System.err.println("sth. is wrong with br.readline() ");
}
//发送消息
while(w_buff.hasRemaining())
sc.write(w_buff);
w_buff.clear();
//进入接收状态
Rec();
//间隔1秒
Thread.currentThread().sleep(1000);
}
}catch(IOException ioe){
ioe.printStackTrace();
}
catch(InterruptedException ie){
ie.printStackTrace();
}
}
////////////
//读取server端发回的数据,并显示
public void Rec() throws IOException{
int count;
r_buff.clear();
count=sc.read(r_buff);
r_buff.flip();
byte[] temp = new byte[r_buff.limit()];
r_buff.get(temp);
System.out.println("reply is " + count +" long, and content is: " + new String(temp));
}
public static void main(String args[]){
if(args.length < 1){//输入需有主机名或IP地址
try{
System.err.println("Enter host name: ");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
host = br.readLine();
}catch(IOException ioe){
System.err.println("sth. is wrong with br.readline() ");
}
}
else if(args.length == 1){
host = args[0];
}
else if(args.length > 1){
host = args[0];
port = Integer.parseInt(args[1]);
}
new AsyncClient();
}
}
在当前目录下运行:
javac AsynClient.java
后,若无编译出错,确认AsyncServer已经运行的情况下,接下来可运行:
java AsynClient hostname 或 java AsynClient hostname ×××(端口号)
并按提示进行操作即可。
总结
总的来说,用nio进行网络编程还是很有新意的,服务器端软件能在一个线程中维护与众多客户端的通信连接。笔者在本文中试图用一个典型的回射例子说明如何用nio建立最基本的C/S应用。希望大家能试着用用它。
另外,笔者在实践中也发现nio在应用中存在的一些难题,比如如何应用SocketChannel的继承类,以及如何在socketchannel之上应用SSL(Secure Socket Layer)等等,因而希望这篇文章只是抛砖引玉,引起大家对nio作进一步的讨论。
发表评论
-
你真的理解了继承和多态吗?
2008-08-12 09:52 920http://www.blogjava.net/sean/ar ... -
浅析Java语言中的内部类
2008-05-23 09:39 675文章1: http://www.enet.com.cn/art ... -
Java同步机制浅谈
2008-05-09 23:27 672http://dev.csdn.net/article/71/ ... -
日历类的小例子
2008-04-16 23:10 817Calendar cal = Calendar.getInst ... -
Java虚拟机参数配置说明
2008-03-17 17:09 1382转载:http://www.cnblogs.com/huqin ... -
JAVA教程:解析Java的多线程机制
2008-02-29 09:15 701转载:http://tech.163.com/05/1020/ ... -
Java字符编码转换过程说明
2008-01-08 18:29 820转载 http://blog.csdn.net/heh ... -
浅析Java多线程编程中的高级技术
2007-12-26 09:19 704转载:http://www.1-100.org/other/1 ... -
Java对象的强、软、弱和虚引用
2007-09-10 23:22 713转载:http://java.chinaitlab.com/o ... -
Java异常学习心得
2007-09-07 10:52 947转载:http://columnist.china ... -
Hibernate存取Clob对象
2007-09-05 11:04 843转载:http://www.amuhouse.com/link ... -
Mbean的管理接口
2007-08-30 16:29 1233转载:http://www.51chm.com/spring/ ... -
JDK1.5新特性介绍
2007-08-30 15:56 822转载:http://www.yesky.com/263/185 ... -
实现非阻塞套接字的一种简单方法
2007-08-29 10:09 1580转载:http://www.ibm.com/dev ... -
Java NIO原理和使用
2007-08-28 15:05 2943转载:http://www.jdon.com/co ... -
一篇不错的介绍Java Socket编程的文章
2007-08-28 14:31 964转载:http://java.ccidnet.co ... -
Java Socket编程 Socket传输模式
2007-08-28 14:06 957转载:http://www.bitscn.com/java/n ... -
Java Socket编程
2007-08-28 14:04 1994转载:http://www.bitscn.com/ ... -
AOP是什么?
2007-08-23 23:19 808转载:http://www.jdon.com/AOPdesig ... -
为什么要区分J2EE容器和J2EE应用系统?
2007-08-23 23:17 928我们知道,J2EE应用系统只有部署在J2EE容器中才能运行,那 ...
相关推荐
根据提供的文件信息,我们可以提取并...无论是对于文件操作还是网络编程,Java NIO 都展现出了卓越的性能优势。通过本书的学习,开发者可以全面掌握 Java NIO 的各种特性和技巧,从而写出更加高效可靠的 Java 代码。
在探讨Java.nio与Java.io之间的比较时,我们首先需要理解这两个包在Java编程语言中的核心作用和它们各自的优势。Java.io和Java.nio是Java中处理输入/输出操作的两个主要框架,它们各自拥有独特的特性和应用场景。 #...
Java NIO(New IO)是Java 1.4版本引入的一个新特性,它为Java应用程序提供了非阻塞I/O操作的能力,与传统的IO模型(基于流的I/O和基于缓冲区...理解并掌握Java NIO的这些概念和用法对于提升Java网络编程能力至关重要。
另外,Java.nio还包含网络通信相关的类,如SocketChannel和ServerSocketChannel,它们支持TCP和UDP协议,为网络编程提供了更底层、更高效的接口。与传统的Socket相比,这些通道可以配合选择器一起工作,实现高效的...
在Java编程语言中,工具类(Utility Class)是包含各种静态方法的类,这些方法用于执行特定任务,如数据操作、文件处理、数学计算等。它们通常不包含实例变量,只提供静态方法服务,帮助开发者提高代码的复用性和...
24. **java.net**:网络编程的类,包括Socket、ServerSocket和URL等。 25. **java.nio**:非阻塞I/O(New I/O)包,提供缓冲区、通道和选择器等。 26. **java.nio.channels**:定义了通道和选择器,支持异步I/O...
Java API覆盖了从基本的数据类型操作到高级网络编程的广泛功能。 #### 二、核心包详解 - **java.applet**:该包提供了创建Applet所需的基本功能,如显示图像、播放声音等。Applet是一种可以在Web浏览器中运行的小型...
1. **网络编程**:Java NIO在服务器端开发中,特别是高并发的TCP连接处理,如聊天服务器、游戏服务器等。 2. **大文件处理**:处理大文件时,NIO的直接内存访问和非阻塞特性可以提高性能。 3. **高性能数据交换**...
通过学习《Apress.Pro.Java.7.NIO.2.2011》,开发者能够熟练掌握NIO和NIO 2的相关技术,从而在实际项目中编写出更高效、更稳定的并发程序,特别是对于网络编程和大数据处理等领域,NIO的知识是必不可少的。...
在实际开发中,NIO常被应用于网络编程、文件系统操作以及高性能服务器的设计等领域。例如,使用NIO可以构建一个简单的聊天服务器,或者创建一个处理大量并发HTTP请求的Web服务器。通过深入理解NIO,你可以更好地优化...
4. **选择器使用**:通过`Selector.open()`创建选择器,然后用`channel.register(selector, interestOps)`方法将感兴趣的通道和事件注册到选择器上。`interestOps`通常包含`SelectionKey.OP_READ`和`SelectionKey.OP...
在Java编程语言中,修改文件编码是一项常见的任务,特别是在处理不同源代码或数据文件时。本文将深入探讨如何使用Java来实现这一功能,主要关注以下几个关键知识点: 1. **字符编码的理解**:字符编码是将字符与二...
总的来说,Java NIO API提供了一种更加高效、灵活的I/O编程模型,它通过Buffer、Channel和Selector这三个核心组件,实现了数据的缓冲和异步传输,极大地提升了Java在处理I/O操作时的性能和并发能力。开发者可以根据...
本文档旨在对一份名为“java帮助文档 chm格式 java中文帮助文档chm格式”的资料进行深入分析,该资料涵盖了Java平台标准版5.0的主要特性及API介绍。由于CHM格式文件本身无法直接在此环境中展示,本文将根据描述和...
### Java NIO API详解 #### 一、引言 在Java早期版本中,I/O操作主要依赖于`java.io`包中的流式API,这些API虽然简单易用,但其本质是阻塞式的,这...随着技术的发展,NIO已经成为现代Java网络编程不可或缺的一部分。
- **java.util.concurrent** 包:提供了高级并发工具,如ExecutorService、Semaphore、CountDownLatch等,便于进行并发编程。 4. **网络编程** - **java.net** 包:包含了Socket、ServerSocket、URL等类,支持TCP...
6. **配置和使用**:配置`httpcore-nio`通常涉及创建`Selector`,注册`SocketChannel`,然后在一个循环中调用`Selector.select()`方法等待事件,处理这些事件并进行相应的I/O操作。 7. **性能优化**:通过合理设置...
1. **Java网络编程基础**:首先,书中会介绍Java中的Socket编程,包括TCP和UDP协议的基础知识,以及如何使用Java的Socket和ServerSocket类创建客户端和服务器端的连接。 2. **I/O与NIO**:Java的I/O流系统是网络...