Java.nio

附件里为阻塞模式、非阻塞模式、阻塞和非阻塞的混合模式代码。

下面为非阻塞的一段客户端和服务器的代码:
服务器端代码:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

/**
* 非阻塞模式服务器
* */
public class EchoNoblockServer {

private Selector selector = null;
private ServerSocketChannel serverSocketChannel = null;
private int port = 8000;
private Charset charset = Charset.forName("GBK");

public EchoNoblockServer() throws IOException{
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().setReuseAddress(true);
serverSocketChannel.configureBlocking(false);
serverSocketChannel.socket().bind(new InetSocketAddress(port));
System.out.println("服务器启动");
}

public void service() throws IOException{
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (selector.select() > 0){
Set readyKeys = selector.selectedKeys();
Iterator it = readyKeys.iterator();
while (it.hasNext()){
SelectionKey key = null;
try{
key = (SelectionKey) it.next();
it.remove();

if (key.isAcceptable()) {
ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
SocketChannel socketChannel = (SocketChannel) ssc.accept();
System.out.println("接收到客户连接,来自:" + socketChannel.socket().getInetAddress() + ":" + socketChannel.socket().getPort());
socketChannel.configureBlocking(false);
ByteBuffer buffer = ByteBuffer.allocate(1024);
socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE, buffer);
}
if (key.isReadable()) {
receive(key);
}
if (key.isWritable()) {
send(key);
}
}catch(IOException e){
e.printStackTrace();
try{
if(key != null){
key.cancel();
key.channel().close();
}
}catch(Exception ex){
e.printStackTrace();
}
}
}//#while
}//#while
}

public void send(SelectionKey key) throws IOException{
ByteBuffer buffer = (ByteBuffer)key.attachment();
SocketChannel socketChannel = (SocketChannel)key.channel();
buffer.flip(); //把极限设为位置,把位置设为0
String data = decode(buffer);
if(data.indexOf("\r\n") == -1) return;
String outputData = data.substring(0, data.indexOf("\n")+1);
System.out.print(outputData);
ByteBuffer outputBuffer = encode("echo:"+outputData);
while(outputBuffer.hasRemaining())
socketChannel.write(outputBuffer);

ByteBuffer temp = encode(outputData);
buffer.position(temp.limit());
buffer.compact();

if(outputData.equals("bye\r\n")){
key.cancel();
socketChannel.close();
System.out.println("关闭与客户的连接");
}
}

public void receive(SelectionKey key) throws IOException{
ByteBuffer buffer = (ByteBuffer)key.attachment();

SocketChannel socketChannel = (SocketChannel)key.channel();
ByteBuffer readBuff = ByteBuffer.allocate(32);
socketChannel.read(readBuff);
readBuff.flip();

buffer.limit(buffer.capacity());
buffer.put(readBuff);
}

public String decode(ByteBuffer buffer){ //解码
CharBuffer charBuffer = charset.decode(buffer);
return charBuffer.toString();
}
public ByteBuffer encode(String str){ //编码
return charset.encode(str);
}

/**
* @param args
*/
public static void main(String[] args) {
EchoNoblockServer server;
try {
server = new EchoNoblockServer();
server.service();
} catch (IOException e) {
e.printStackTrace();
}
}

}

客户端代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

/**
* 非阻塞模式客户端
* */
public class EchoNoblockClient {

private SocketChannel socketChannel = null;
private ByteBuffer sendBuffer = ByteBuffer.allocate(1024);
private ByteBuffer receiveBuffer = ByteBuffer.allocate(1024);
private Charset charset = Charset.forName("GBK");
private Selector selector;

public EchoNoblockClient() throws IOException {
socketChannel = SocketChannel.open();
InetAddress ia = InetAddress.getLocalHost();
InetSocketAddress isa = new InetSocketAddress(ia, 8000);
socketChannel.connect(isa);
socketChannel.configureBlocking(false);
System.out.println("与服务器的连接建立成功");
selector=Selector.open();
}

public void receiveFromUser(){
try{
BufferedReader localReader = new BufferedReader(new InputStreamReader(System.in));
String msg = null;
while((msg=localReader.readLine()) != null){
synchronized(sendBuffer){
sendBuffer.put(encode(msg + "\r\n"));
}
if(msg.equals("bye"))
break;
}
}catch(IOException e){
e.printStackTrace();
}
}

public void talk() throws IOException {
socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
while (selector.select() > 0){
Set readyKeys = selector.selectedKeys();
Iterator it = readyKeys.iterator();
while (it.hasNext()){
SelectionKey key = null;
try{
key = (SelectionKey) it.next();
it.remove();

if (key.isReadable()) {
receive(key);
}
if (key.isWritable()) {
send(key);
}
}catch(IOException e){
e.printStackTrace();
try{
if(key != null){
key.cancel();
key.channel().close();
}
}catch(Exception ex){
e.printStackTrace();
}
}
}//#while
}//#while
}

public void send(SelectionKey key) throws IOException{
SocketChannel socketChannel = (SocketChannel)key.channel();
synchronized(sendBuffer){
sendBuffer.flip(); //把极限设为位置
socketChannel.write(sendBuffer);
sendBuffer.compact();
}
}
public void receive(SelectionKey key) throws IOException{
SocketChannel socketChannel = (SocketChannel)key.channel();
socketChannel.read(receiveBuffer);
receiveBuffer.flip();
String receiveData = decode(receiveBuffer);

if(receiveData.indexOf("\n") == -1) return;

String outputData = receiveData.substring(0, receiveData.indexOf("\n")+1);
System.out.print(outputData);
if(outputData.equals("echo:bye\r\n")){
key.cancel();
socketChannel.close();
System.out.println("关闭与服务器的连接");
selector.close();
System.exit(0);
}

ByteBuffer temp = encode(outputData);
receiveBuffer.position(temp.limit());
receiveBuffer.compact();
}

public String decode(ByteBuffer buffer){ //解码
CharBuffer charBuffer = charset.decode(buffer);
return charBuffer.toString();
}
public ByteBuffer encode(String str){ //编码
return charset.encode(str);
}

/**
* @param args
*/
public static void main(String[] args) {
final EchoNoblockClient client;
try {
client = new EchoNoblockClient();
Thread receiver = new Thread(){
public void run(){
client.receiveFromUser();
}
};

receiver.start();
client.talk();
} catch (IOException e) {
e.printStackTrace();
}
}

}

Ping客户端代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.LinkedList;

/**
* 非阻塞模式Ping客户端
* */
public class PingNoblockClient {

private Selector selector;
//存放用户新提交的任务
private LinkedList targets = new LinkedList();
//存放已经完成的需要打印的任务
private LinkedList finishedTargets = new LinkedList();

public PingNoblockClient() throws IOException{
selector=Selector.open();
Connector connector = new Connector();
Printer printer = new Printer();
connector.start();
printer.start();
receiveTarget();
}

public void addTarget(Target target) {
//向targets队列中加入一个任务
SocketChannel socketChannel = null;
try {
socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.connect(target.address);

target.channel = socketChannel;
target.connectStart = System.currentTimeMillis();

synchronized (targets) {
targets.add(target);
}
selector.wakeup();
} catch (Exception x) {
if (socketChannel != null) {
try {
socketChannel.close();
} catch (IOException xx) { }
}
target.failure = x;
addFinishedTarget(target);
}
}

public void addFinishedTarget(Target target) {
//向finishedTargets队列中加入一个任务
synchronized (finishedTargets) {
finishedTargets.notify();
finishedTargets.add(target);
}
}

public void printFinishedTargets() {
//打印finisedTargets队列中的任务
try {
for (;;) {
Target target = null;
synchronized (finishedTargets) {
while (finishedTargets.size() == 0)
finishedTargets.wait();
target = (Target)finishedTargets.removeFirst();
}
target.show();
}
} catch (InterruptedException x) {
return;
}
}

public void registerTargets(){
//取出targets队列中的任务,向Selector注册连接就绪事件
synchronized (targets) {
while (targets.size() > 0) {
Target target = (Target)targets.removeFirst();

try {
target.channel.register(selector, SelectionKey.OP_CONNECT, target);
} catch (IOException x) {
try{
target.channel.close();
}catch(IOException e){
e.printStackTrace();
}
target.failure = x;
addFinishedTarget(target);
}
}
}
}

public void processSelectedKeys() throws IOException {
//处理连接就绪事件
for (Iterator it = selector.selectedKeys().iterator(); it.hasNext();) {
SelectionKey selectionKey = (SelectionKey)it.next();
it.remove();

Target target = (Target)selectionKey.attachment();
SocketChannel socketChannel = (SocketChannel)selectionKey.channel();

try {
if (socketChannel.finishConnect()) {
selectionKey.cancel();
target.connectFinish = System.currentTimeMillis();
socketChannel.close();
addFinishedTarget(target);
}
} catch (IOException x) {
socketChannel.close();
target.failure = x;
addFinishedTarget(target);
}
}
}

public void receiveTarget(){
//接收用户输入的地址,向targets队列中加入任务
try{
BufferedReader localReader = new BufferedReader(new InputStreamReader(System.in));
String msg=null;
while((msg=localReader.readLine()) != null){
if(!msg.equals("bye")){
Target target = new Target(msg);
addTarget(target);
}else{
shutdown = true;
selector.wakeup();
break;
}
}
}catch(IOException e){
e.printStackTrace();
}
}

/**
* @param args
*/
public static void main(String[] args) {
try {
new PingNoblockClient();
} catch (IOException e) {
e.printStackTrace();
}
}

boolean shutdown = false;

public class Printer extends Thread{
public Printer(){
setDaemon(true);
}
public void run(){
printFinishedTargets();
}
}

public class Connector extends Thread{
public void run(){
while (!shutdown) {
try {
registerTargets();
if (selector.select() > 0) {
processSelectedKeys();
}
} catch (Exception e) {
e.printStackTrace();
}
}
try{
selector.close();
}catch(IOException e){e.printStackTrace();}
}
}
}

class Target { //表示一项任务
InetSocketAddress address;
SocketChannel channel;
Exception failure;
long connectStart; //开始连接时的时间
long connectFinish = 0; //连接成功时的时间
boolean shown = false; //该任务是否已经打印

Target(String host) {
try {
address = new InetSocketAddress(InetAddress.getByName(host), 80);
} catch (IOException x) {
failure = x;
}
}

void show() { //打印任务执行的结果
String result;
if (connectFinish != 0)
result = Long.toString(connectFinish - connectStart) + "ms";
else if (failure != null)
result = failure.toString();
else
result = "Timed out";

System.out.println(address + " : " + result);
shown = true;
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值