基于Nio的计算器
- StartServer.java
package com.tust.nio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
public class StartServer {
public StartServer() throws IOException{
//1、获取Selector选择器
Selector selector = Selector.open();
//2、获取通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//3、设置为非阻塞
serverSocketChannel.configureBlocking(false);
//4、绑定连接
serverSocketChannel.bind(new InetSocketAddress(8888));
System.out.println("服务器启动成功!");
//5将通道注册到选择器上,并注册的IO事件为:“接收新连接”
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
//6、轮询感兴趣的I/O就绪事件(选择键集合)
while (selector.select() > 0) {
//7、获取选择键集合
Iterator<SelectionKey> selectedKeys = selector.selectedKeys().iterator();
while (selectedKeys.hasNext()) {
//8、获取单个的选择键,并处理
SelectionKey selectedKey = selectedKeys.next();
//9、判断key是具体的什么事件
if(selectedKey.isAcceptable()) {
//10、若选择键的IO事件是“连接就绪”事件,就获取客户端连接
SocketChannel socketChannel = serverSocketChannel.accept();
//11、切换为非阻塞模式
socketChannel.configureBlocking(false);
//12、将该通道注册到selector选择器上
socketChannel.register(selector,SelectionKey.OP_READ);
}else if(selectedKey.isReadable()) {
//13、若选择键的IO事件是“可读”事件,读取数据
SocketChannel socketChannel = (SocketChannel) selectedKey.channel();
//14、读取数据
ByteBuffer byteBuffer = ByteBuffer.allocate(8);
int count = socketChannel.read(byteBuffer);
if (count > 0){
StringBuilder sb = new StringBuilder();
for (byte bb : byteBuffer.array()) {
if (bb != 0){
sb.append((char) bb);
}
}
String mess = sb.toString();
int result = new Calculate().cal(mess);
String str = mess + " = " + result;
System.out.println(str);
//发消息
socketChannel.write(ByteBuffer.wrap(str.getBytes()));
}
}
//15、移除选择键
selectedKeys.remove();
}
}
//16、关闭连接
serverSocketChannel.close();
}
public static void main(String[] args) throws IOException {
new StartServer();
}
}
- StartClient.java
package com.tust.nio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Scanner;
public class StartClient {
private SocketChannel socketChannel;
public StartClient() throws IOException{
InetSocketAddress address = new InetSocketAddress("127.0.0.1",8888);
//1、获取通道(channel)
socketChannel = SocketChannel.open(address);
//2、切换为非阻塞模式
socketChannel.configureBlocking(false);
//不断的自旋、等待连接完成,或者做些其他的事情
while(!socketChannel.finishConnect()) {}
System.out.println("客户端连接成功!");
}
//发送消息
private void sendInfo(String info){
try {
socketChannel.write(ByteBuffer.wrap(info.getBytes()));
} catch (IOException e) {
e.printStackTrace();
}
}
//读取从服务器端回复的消息
private void readInfo(){
try {
ByteBuffer buf = ByteBuffer.allocate(1024);
int count = socketChannel.read(buf);
if (count > 0){
String str = new String(buf.array());
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
StartClient sc = new StartClient();
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()){
sc.sendInfo(scanner.nextLine());
Thread.sleep(200);
sc.readInfo();
}
}
}
- Calculate.java
package com.tust.nio;
public class Calculate {
public Integer cal(String mess) {
String[] arr = mess.split(" "); //将mess的内容放入arr数组
if(arr.length == 3 && arr[1].equals("+")) { //如果arr数组第二个字符存在且是+,就进行下面操作;
int sum;
int a = Integer.parseInt(arr[0]); //把arr数组的第一个字符串转换成数字型
int b = Integer.parseInt(arr[2].trim()); //把arr数组的第三个字符串转换成数字型
sum = a + b;
return sum;
}
else if(arr.length > 1 && arr[1].equals("-")){
int del;
int a = Integer.parseInt(arr[0]);
int b = Integer.parseInt(arr[2].trim());
del = a - b;
return del;
}
else if(arr.length > 1 && arr[1].equals("*")){
int pro;
int a = Integer.parseInt(arr[0]);
int b = Integer.parseInt(arr[2].trim());
pro = a * b;
return pro;
}
else if(arr.length > 1 && arr[1].equals("/")){
int quo;
int a = Integer.parseInt(arr[0]);
int b = Integer.parseInt(arr[2].trim());
quo = a / b;
return quo;
}
return 0;
}
}
演示: