一个简单的echo服务器,客户端向服务端发送消息,服务端进行响应,当客户端发送quit字符串时,断开客户端和服务端的连接。使用NIO实现
服务端代码
public class EchoServer_NIO {
private Selector selector;
private ByteBuffer sendBuf = ByteBuffer.allocate(1024);
private ByteBuffer recBuf = ByteBuffer.allocate(1024);
public EchoServer_NIO(){
try {
System.out.println("服务器正在启动");
selector = Selector.open();
ServerSocketChannel ssc = ServerSocketChannel.open();
//设置非阻塞模式
ssc.configureBlocking(false);
//绑定端口
ssc.bind(new InetSocketAddress(8777));
ssc.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("服务器启动成功");
} catch (Exception e) {
e.printStackTrace();
System.out.println("服务器启动失败");
}
}
public static void main(String[] args) {
new EchoServer_NIO().service();
}
public void service(){
while (true){
try {
int select = selector.select();
if (select>0){
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()){
SelectionKey key = iterator.next();
iterator.remove();
//如果是有效的
if (key.isValid()){
if (key.isAcceptable()){
accept(key);
}else if(key.isReadable()){
read(key);
}else if(key.isWritable()){
write(key);
}
}
}
selectionKeys.clear();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void accept(SelectionKey key){
try {
ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
SocketChannel sc = ssc.accept();
sc.configureBlocking(false);
sc.register(selector,SelectionKey.OP_READ);
}catch (Exception e){
e.printStackTrace();
}
}
private void read(SelectionKey key) {
try {
recBuf.clear();
SocketChannel sc = (SocketChannel) key.channel();
int read = sc.read(recBuf);
if (read<0){
key.channel().close();
key.cancel();
return;
}
recBuf.flip();
String recText = new String(recBuf.array(),0,read);
System.out.println(recText);
if (recText.equals("quit")){
sendBuf.clear();
sendBuf.put("bye".getBytes());
sc.write(sendBuf);
key.channel().close();
key.cancel();
return;
}
sc.register(selector,SelectionKey.OP_WRITE);
}catch (Exception e){
e.printStackTrace();
}
}
private void write(SelectionKey key) {
try {
SocketChannel sc = (SocketChannel) key.channel();
sendBuf.clear();
String sendText = "hello";
sendBuf.put(sendText.getBytes());
sendBuf.flip();
sc.write(sendBuf);
sc.register(selector,SelectionKey.OP_READ);
}catch (Exception e){
e.printStackTrace();
}
}
}
客户端代码
public class EchoClient_NIO {
private Selector selector;
private ByteBuffer sendBuf = ByteBuffer.allocate(1024);
private ByteBuffer revBuf = ByteBuffer.allocate(1024);
public EchoClient_NIO(){
try {
System.out.println("正在连接服务器...");
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
selector = Selector.open();
socketChannel.register(selector, SelectionKey.OP_CONNECT);
socketChannel.connect(new InetSocketAddress("localhost",8777));
}catch (Exception e){
e.printStackTrace();
}
}
public void service() throws IOException {
while (true){
selector.select();
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iterator = keys.iterator();
while (iterator.hasNext()){
SelectionKey key = iterator.next();
iterator.remove();
if (key.isConnectable()){
connect(key);
}else if (key.isReadable()){
read(key);
}else if (key.isWritable()){
write(key);
}
keys.clear();
}
}
}
private void connect(SelectionKey key) {
try {
SocketChannel sc = (SocketChannel) key.channel();
if (sc.isConnectionPending()){
sc.finishConnect();
System.out.println("服务器连接成功");
sc.register(selector,SelectionKey.OP_WRITE);
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("服务器连接失败");
}
}
private void read(SelectionKey key) {
try {
revBuf.clear();
SocketChannel sc = (SocketChannel) key.channel();
int read = sc.read(revBuf);
if (read>0) {
revBuf.flip();
String recText = new String(revBuf.array(), 0, read);
System.out.println(recText);
if (recText.equals("quit")) {
key.channel().close();
key.cancel();
return;
}
sc.register(selector, SelectionKey.OP_WRITE);
}
}catch (Exception e){
e.printStackTrace();
}
}
private void write(SelectionKey key) {
try {
sendBuf.clear();
SocketChannel sc = (SocketChannel) key.channel();
Scanner scanner = new Scanner(System.in);
String message = scanner.nextLine();
sendBuf.put(message.getBytes());
sendBuf.flip();
sc.write(sendBuf);
if (message.equals("quit")){
key.channel().close();
key.cancel();
selector.close();
return;
}
sc.register(selector,SelectionKey.OP_READ);
}catch (Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
new EchoClient_NIO().service();
}
}
NIO不易使用,使用时需谨慎