`
阅读更多
http://topic.csdn.net/u/20090223/01/5a8b1312-647c-4b0e-a988-37be86fab317.html
无阻塞sock编程,可以用nio啊 
给个实例 
import java.io.*; //引入Java.io包 
import java.net.*; //引入Java.net包 
import java.nio.channels.*; //引入Java.nio.channels包 
import java.util.*; //引入Java.util包 
public class TestServer implements Runnable 

{ 
/** 

* 服务器Channel对象,负责接受用户连接 
*/ 
private ServerSocketChannel server; 
/** 
* Selector对象,负责监控所有的连接到服务器的网络事件的发生 
*/ 
private Selector selector; 
/** 
* 总的活动连接数 
*/ 
private int activeSockets; 
/** 
* 服务器Channel绑定的端口号 
*/ 
private int port ; 
/** 
* 
* 构造函数 
*/ 
public TestServer()throws IOException 
{ 
activeSockets=0; 
port=9999;//初始化服务器Channel绑定的端口号为9999 
selector= Selector.open();//初始化Selector对象 
server=ServerSocketChannel.open();//初始化服务器Channel对象 
ServerSocket socket=server.socket();//获取服务器Channel对应的//ServerSocket对象 
socket.bind(new InetSocketAddress(port));//把Socket绑定到监听端口9999上 
server.configureBlocking(false);//将服务器Channel设置为非阻塞模式 
server.register(selector,SelectionKey.OP_ACCEPT);//将服务器Channel注册到 
Selector对象,并指出服务器Channel所感兴趣的事件为可接受请求操作 
} 
public void run() 
{ 
while(true) 
{ 
try 
{ 
/** 
*应用Select机制轮循是否有用户感兴趣的新的网络事件发生,当没有 

* 新的网络事件发生时,此方法会阻塞,直到有新的网络事件发生为止 
*/ 
selector.select(); 

} 
catch(IOException e) 
{ 
continue;//当有异常发生时,继续进行循环操作 
} 
/** 
* 得到活动的网络连接选择键的集合 
*/ 
Set <SelectionKey> keys=selector.selectedKeys(); 
activeSockets=keys.size();//获取活动连接的数目 
if(activeSockets==0) 
{ 
continue;//如果连接数为0,则继续进行循环操作 
} 
/** 

/** 
* 应用For—Each循环遍历整个选择键集合 
*/ 
for(SelectionKey key :keys) 
{ 
/** 
* 如果关键字状态是为可接受,则接受连接,注册通道,以接受更多的* 
事件,进行相关的服务器程序处理 
*/ 
if(key.isAcceptable()) 
{ 
doServerSocketEvent(key); 
continue; 
} 
/** 
* 如果关键字状态为可读,则说明Channel是一个客户端的连接通道, 
* 进行相应的读取客户端数据的操作 
*/ 
if(key.isReadable()) 
{ 
doClientReadEvent(key); 

continue; 

} 
/** 
* 如果关键字状态为可写,则也说明Channel是一个客户端的连接通道, 
* 进行相应的向客户端写数据的操作 
*/ 
if(key.isWritable()) 
{ 
doClinetWriteEvent(key); 
continue; 
} 
} 
} 
} 

/** 
* 处理服务器事件操作 
* @param key 服务器选择键对象 
*/ 
private void doServerSocketEvent(SelectionKey key) 
{ 
SocketChannel client=null; 
try 
{ 
ServerSocketChannel server=(ServerSocketChannel)key.channel(); 
client=server.accept(); 
if(client==null) 
{ 
return; 
} 
client.configureBlocking(false);//将客户端Channel设置为非阻塞型 
/** 

/** 
* 将客户端Channel注册到Selector对象上,并且指出客户端Channel所感 
* 兴趣的事件为可读和可写 
*/ 
client.register(selector,SelectionKey.OP_READ|SelectionKey.OP_READ); 
}catch(IOException e) 
{ 
try 
{ 
client.close(); 

}catch(IOException e1){} 
} 
} 
/** 
* 进行向客户端写数据操作 
* @param key 客户端选择键对象 
*/ 
private void doClinetWriteEvent(SelectionKey key) 
{ 
代码实现略; 
} 
/** 
* 进行读取客户短数据操作 
* @param key 客户端选择键对象 
*/ 
private void doClientReadEvent(SelectionKey key) 
{ 
代码实现略; 
} 
} 

从上面对代码可以看出,使用非阻塞性I/O进行并发型服务器程序设计分三个部分:1. 
向Selector对象注册感兴趣的事件;2.从Selector中获取所感兴趣的事件;3.根据不同的事件进 
行相应的处理。 


结语 




通过使用NIO 工具包进行并发型服务器程序设计,一个或者很少几个Socket 线程就可 
以处理成千上万个活动的Socket 连接,大大降低了服务器端程序的开销;同时网络I/O 采取 
非阻塞模式,线程不再在读或写时阻塞,操作系统可以更流畅的读写数据并可以更有效地向 
CPU 传递数据进行处理,以便更有效地提高系统的性能 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics