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.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.util.Iterator;
public class Server extends Thread{
static int MAX_LEN = 2048;
// 定义检测SocketChannel的Selector对象
protected Selector selector = null;
protected ByteBuffer buff = ByteBuffer.allocate(MAX_LEN);
// 定义处理编码和解码的字符集
static CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
protected CharsetDecoder decoder = null;
public Server(int port) throws IOException {
selector = this.getSelector(port);
Charset charset = Charset.forName("UTF-8");
decoder = charset.newDecoder();
}
// 获取Selector
protected Selector getSelector(int port) throws IOException {
// 通过open方法来打开一个未绑定的ServerSocketChannel实例
ServerSocketChannel server = ServerSocketChannel.open();
// 打开一个selector
Selector sel = Selector.open();
// public InetSocketAddress(intport)
// 服务器端的程序是以通配符IP来绑定,简单来说任何一台到服务器的客户端机器只要物理线路能够走通,就能够使用这个socket服务,无论是用哪个线路。
server.socket().bind(new InetSocketAddress(port));
// 设置ServerSocket以非阻塞方式工作
server.configureBlocking(false);
// 将server注册到指定Selector对象
server.register(sel, SelectionKey.OP_ACCEPT);
return sel;
}
// 监听端口
public void listen() {
//while (true) {
try {
// Wait for anevent
selector.select(50000);
} catch (IOException e) {
// Handle errorwith selector
//break;
}
// Get list ofselection keys with pending events
Iterator iter = selector.selectedKeys().iterator();
// Process eachkey at a time
while (iter.hasNext()) {
// Get the selection key
SelectionKey key = (SelectionKey) iter.next();
// Remove it fromthe list to indicate that it is being processed
iter.remove();
try {
process(key);
} catch (IOException e) {
// Handle errorwith channel and unregister
key.cancel();
}
}
}
//}
// 处理事件
protected void process(SelectionKey key) throws IOException {
// Since the ready operationsare cumulative,
// need to check readiness for each operation
if (key.isValid() && key.isAcceptable()) { // 接收请求
System.out.println("acceptable.");
ServerSocketChannel server = (ServerSocketChannel)key.channel();
// 调用accept方法接受连接,产生服务器端对应的SocketChannel
SocketChannel channel = server.accept();
// 设置非阻塞模式
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ);
}
if (key.isValid() && key.isConnectable()) {
System.out.println("connectable.");
// Get channel with connection request
SocketChannelsChannel = (SocketChannel)key.channel();
boolean success =sChannel.finishConnect();
if (!success) {
// An error occurred; handle it
// Unregister the channel with this selector
key.cancel();
}
}
if (key.isValid() && key.isReadable()) { // 读信息
System.out.println("read.");
SocketChannel channel = (SocketChannel) key.channel();
try {
// Clear the buffer and read bytes from socket
buff.clear();
int numBytesRead =channel.read(buff);
if (numBytesRead ==-1) {
// No more bytes can be read from the channel
channel.close();
} else {
// To read the bytes, flip the buffer
buff.flip();
// Read the bytes from the buffer ...;
// see Getting Bytes from a ByteBuffer
CharBuffercharBuffer = decoder.decode(buff);
System.out.println(charBuffer);
channel.register(selector,SelectionKey.OP_WRITE);
}
} catch (IOException e) {
// Connection may have been closed
}
}
if (key.isValid() && key.isWritable()) { // 写事件
System.out.println("write.");
SocketChannel sc = (SocketChannel) key.channel();
try {
// Fill the buffer with the bytes to write;
// see Putting Bytes into a ByteBuffer
//buff.put((byte)0xFF);
// Prepare the buffer for reading by the socket
buff.flip();
// Write bytes
//int numBytesWritten = sc.write(buff);
String str = "test test test";
buff = encoder.encode(CharBuffer.wrap("Hello !" + str));
sc.write(buff);
sc.register(selector,SelectionKey.OP_READ);
} catch (IOException e) {
// Connection may have been closed
}
}
}
public static void main(String[] args) {
int port = 9696;
try {
Server server = new Server(port);
System.out.println("listeningon " + port);
server.listen();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("abc");
}
}