异步通信基石NIO模拟客户端和服务端

来源:互联网 发布:爱的算法 mobi 编辑:程序博客网 时间:2024/05/24 01:41

客户端 

package chapter1;



import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;


public class NIOClient {
SocketChannel client;

InetSocketAddress serverAddress = new InetSocketAddress("localhost", 8080);

Selector selector;

ByteBuffer receiveBuffer = ByteBuffer.allocate(1024);
ByteBuffer sendBuffer = ByteBuffer.allocate(1024);

public NIOClient() throws IOException{

client = SocketChannel.open();

client.configureBlocking(false);

client.connect(serverAddress);

selector = Selector.open();

client.register(selector, SelectionKey.OP_CONNECT);

}

public void session() throws IOException{

if(client.isConnectionPending()){
client.finishConnect();

client.register(selector, SelectionKey.OP_WRITE);

System.out.println("已经连接到服务器,可以在控制台登记了");
}

Scanner scan = new Scanner(System.in);
while(scan.hasNextLine()){
String name = scan.nextLine();
if("".equals(name))continue;
if("finish".equals(name))System.exit(0);

process(name);
}
}


private void process(String name) throws IOException{

boolean waitHelp = true;
Iterator<SelectionKey> iterator = null;
Set<SelectionKey> keys = null;
while(waitHelp){
try {
int readys = selector.select();
if(readys == 0)continue;
keys = selector.selectedKeys();
iterator = keys.iterator();
while(iterator.hasNext()){
SelectionKey key = iterator.next();
if(key.isValid() && key.isWritable()){
//判断是否可写,可写代表客户端要对服务端发送消息
sendBuffer.clear();
sendBuffer.put(name.getBytes());
sendBuffer.flip();

client.write(sendBuffer);

client.register(selector, SelectionKey.OP_READ);
}else if(key.isValid() && key.isReadable()){

receiveBuffer.clear();
int len = client.read(receiveBuffer);
if(len>0){
receiveBuffer.flip();
System.out.println("服务端反馈的消息:"+new String(receiveBuffer.array()));
client.register(selector, SelectionKey.OP_WRITE);
waitHelp = false;
}

//检查完之后,打发客户走
iterator.remove();
}
}

} catch (Exception e) {
((SelectionKey) keys).cancel();
client.socket().close();
client.close();
return;
}
}
}

public static void main(String[] args) {
try {
NIOClient client = new NIOClient();
client.session();
} catch (IOException e) {
e.printStackTrace();
}
}

}



服务端

package chapter1;


import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;


public class NIOServer {
private ServerSocketChannel server;
int port = 8080;
//注册器
private Selector selector;
//数据缓冲区
ByteBuffer recBuffer = ByteBuffer.allocate(1024);
ByteBuffer sendBuffer = ByteBuffer.allocate(1024);
//中间消息缓存设置
private Map<SelectionKey, String> sessionMaps = new HashMap<SelectionKey, String>();

public NIOServer(int port) throws IOException{
this.port = port;
//开启服务
server = ServerSocketChannel.open();
//绑定端口
server.socket().bind(new InetSocketAddress(port));
//服务设置为非阻塞
server.configureBlocking(false);
selector = Selector.open();

server.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("NIO服务已经启动,监听端口是:"+this.port);
}

public void listener() throws IOException{
while(true){
int eventCount = selector.select();
if(eventCount == 0){
continue;
}
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iterator = keys.iterator();
while(iterator.hasNext()){
//通过事件类型的标签来处理业务
process(iterator.next());
//处理完成后移除key
iterator.remove();
}
}
}

private void process(SelectionKey key) {
SocketChannel client = null;
try {
if(key.isValid() && key.isAcceptable()){
client = server.accept();
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);

}else if (key.isValid() && key.isReadable()){
//读取客户端请求信息
recBuffer.clear();
client = (SocketChannel)key.channel();
int len = client.read(recBuffer);
if(len > 0){
String msg = new String(recBuffer.array(), 0, len);
sessionMaps.put(key, msg);
System.out.println("获取客户端id"+ Thread.currentThread().getId() +"发送来的信息:" + msg);
client.register(selector, SelectionKey.OP_WRITE);
}
}else if (key.isValid() && key.isWritable()){
if(!sessionMaps.containsKey(key)){
return;
}
//响应客户端请求信息
sendBuffer.clear();
sendBuffer.put(new String(sessionMaps.get(key)+",您好,您的请求我已经处理完成").getBytes());
//切换我们的操作位
sendBuffer.flip();
client = (SocketChannel)key.channel();
client.write(sendBuffer);
client.register(selector, SelectionKey.OP_READ);
}
} catch (IOException e) {
try {
//客户端可能异常下线
key.cancel();
client.socket().close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}


public static void main(String[] args) {
try {
new NIOServer(8080).listener();
} catch (IOException e) {
e.printStackTrace();
}
}
}











0 0
原创粉丝点击