前几天做了一个linux下的socket实验使用了select,可以让程序在不使用多线程的情况下,实现io的异步,也就是可以收数据,也可以发数据,但不阻塞。
于是我就想能不能移植到Java下来实现。结果我发现Java也有select类似的功能,但是我发现Java nio的Chanel无法对标准输入进行处理,要发数据的时候就会阻塞。
可能是我技术不够,我想问问大家Java nio到底能不能实现与linux select一样的效果?
package server;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;
import java.nio.ByteBuffer;
import java.nio.channels.Channel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
public class ServerSock {
public ServerSock() {
// TODO Auto-generated constructor stub
try {
ServerSocketChannel server= ServerSocketChannel.open();
server.bind(new InetSocketAddress(InetAddress.getLocalHost(), 8899), 5);
System.out.println("服务器启动....");
Selector selector = Selector.open();
server.configureBlocking(false);
server.register(selector, SelectionKey.OP_ACCEPT);
ByteBuffer buf = ByteBuffer.allocate(48);
SocketChannel channel = null;
while(true){
int a=selector.select();
Iterator<SelectionKey> keyIter = selector.selectedKeys().iterator();
while(keyIter.hasNext()){
SelectionKey key = keyIter.next();
if (key.isAcceptable()) {
channel = server.accept();
System.out.println("接受: ");
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
}else if (key.isReadable()) {
System.out.println("读取:");
int bytesRead = channel.read(buf);
buf.flip();
String aString = new String(buf.array()).trim();
System.out.println(aString);
buf.clear();
}else if (key.isWritable()) {
System.out.println("写入:");
Scanner scanner = new Scanner(System.in);
String b = scanner.nextLine();
buf.put(b.getBytes());
buf.flip();
channel.write(buf);
buf.clear();
}
keyIter.remove();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
new ServerSock();
}
}