服务器
[code="java"]
package test.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 NonBlockEchoServer {
private ServerSocketChannel serverSocketChannel;
private int port = 8992;
private Selector selector;
private Charset charset;
public NonBlockEchoServer() throws IOException {
charset = Charset.forName("UTF-8");
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
//可以绑定到同一个端口
serverSocketChannel.socket().setReuseAddress(true);
//设置为非阻塞模式
serverSocketChannel.configureBlocking(false);
serverSocketChannel.socket().bind(new InetSocketAddress(port));
}
public void service() throws IOException {
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while(selector.select() > 0) {
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> it = keys.iterator();
while(it.hasNext()) {
SelectionKey key = null;
try {
key = it.next();
it.remove();
if(key.isAcceptable()) {
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
ByteBuffer byteBuffer = ByteBuffer.allocate(0);
socketChannel.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE, byteBuffer);
}
if(key.isReadable()) {
read(key);
}
if(key.isWritable()) {
write(key);
}
}catch (IOException e) {
if(key != null) {
try {
key.cancel();
key.channel().close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
e.printStackTrace();
}
}
}
}
private void write(SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer byteBuffer = (ByteBuffer) key.attachment();
byteBuffer.flip();
String data = decode(byteBuffer);
if(data.indexOf("\r\n") == -1) {
return;
}
String outputData = data.substring(0, data.indexOf("\n")+1);
System.out.println("--->" + outputData);
ByteBuffer outputBuffer = encode("echo:" + outputData);
while(outputBuffer.hasRemaining()) {
socketChannel.write(outputBuffer);
}
ByteBuffer temp = encode(outputData);
byteBuffer.position(temp.limit());
byteBuffer.compact();
if(outputData.equals("bye\r\n")) {
key.cancel();
socketChannel.close();
System.out.println("链接已经关闭");
}
}
private void read(SelectionKey key) throws IOException {
System.out.println("server read");
SocketChannel socketChannel = (SocketChannel) key.channel();
socketChannel.configureBlocking(false);
ByteBuffer byteBuffer = (ByteBuffer) key.attachment();
ByteBuffer readBuff = ByteBuffer.allocate(32);
socketChannel.read(readBuff);
byteBuffer.limit(byteBuffer.capacity());
readBuff.flip();
byteBuffer.put(readBuff);
}
/**
* 解码
* @param byteBuffer
* @return
*/
private String decode(ByteBuffer byteBuffer) {
CharBuffer charBuffer = charset.decode(byteBuffer);
return charBuffer.toString();
}
/**
* 编码
* @param str
* @return
*/
private ByteBuffer encode(String str) {
return charset.encode(str);
}
public static void main(String[] args) throws IOException {
NonBlockEchoServer nonServer = new NonBlockEchoServer();
nonServer.service();
}
}
[/code]
客户端
[code="java"]
package test.nio;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
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.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;
public class NonBlockEchoClient {
private SocketChannel socketChannel;
private ByteBuffer sendBuffer = ByteBuffer.allocate(1024);
private ByteBuffer receiveBuffer = ByteBuffer.allocate(1024);
Charset charset = Charset.forName("utf-8");
private Selector selector;
private int port = 8992;
public NonBlockEchoClient() throws IOException {
socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress(port));
socketChannel.configureBlocking(false);
System.out.println("与服务器链接成功");
selector = Selector.open();
}
public static void main(String[] args) throws IOException {
final NonBlockEchoClient non = new NonBlockEchoClient();
Thread client = new Thread(new Runnable() {
@Override
public void run() {
non.receiveFromUser();
}
});
client.start();
non.talk();
}
private void talk() throws IOException {
socketChannel.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);
while(selector.select() > 0) {
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> it = keys.iterator();
while(it.hasNext()) {
SelectionKey key = it.next();
it.remove();
if(key.isReadable()) {
receive(key);
}
if(key.isWritable()) {
send(key);
}
}
}
}
public void receiveFromUser() {
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String msg = null;
while((msg = bufferedReader.readLine()) != null) {
System.out.println(msg);
synchronized (sendBuffer) {
sendBuffer.put(encode(msg+"\r\n"));
}
if("bye".equals(msg)) {
break;
}
}
} catch(IOException e) {
e.printStackTrace();
}
}
private void send(SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
synchronized (sendBuffer) {
sendBuffer.flip();
socketChannel.write(sendBuffer);
sendBuffer.compact();
}
}
private void receive(SelectionKey key) throws IOException {
System.out.println("client RECEIVE");
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.println("--->" + outputData);
if(outputData.equals("echo:bye\r\n")) {
key.cancel();
socketChannel.close();
selector.close();
System.exit(0);
}
ByteBuffer temp = encode(outputData);
receiveBuffer.position(temp.limit());
receiveBuffer.compact();
}
private String decode(ByteBuffer byteBuffer) {
return charset.decode(byteBuffer).toString();
}
private ByteBuffer encode(String str) {
return charset.encode(str);
}
}
[/code]
各位大侠,最近小弟在学习nio编程,遇到一个问题:客户端在连接服务器端成功后,没有进行任何操作,服务器端并没有触发 写事件 为什么key.isWritable()一直为true ??