public class SocketSelector {
private final static int PORT = 1234;
public static void main(String[] args) throws IOException {
new SocketSelector().init(args);
}
public void init(String... args) throws IOException{
int port = PORT;
if (args.length != 0) {
port = Integer.parseInt(args[0]);
}
Selector selector = Selector.open();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.socket().bind(new InetSocketAddress(port));
System.out.println("1111");
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("wille to cycle..");
while(true){
int n = selector.select();
if (n == 0) {
continue;
}
<span style="white-space:pre"> </span>System.out.println(n);
Iterator it = selector.selectedKeys().iterator();
while(it.hasNext()){
SelectionKey selectionKey = (SelectionKey) it.next();
it.remove();//如果去掉這句話,在acceptable裏,sayhello函數裏socketchannel會是個null值。我猜測每個key只能使用一次
System.out.println(selectionKey.interestOps());
if(selectionKey.isAcceptable()){
ServerSocketChannel serverSocketChannel2 = (ServerSocketChannel) selectionKey.channel();
System.out.println(selectionKey.interestOps());
SocketChannel socketChannel = serverSocketChannel2.accept();
registerChannel(selector,socketChannel,SelectionKey.OP_READ);
sayHello(socketChannel);
}
if(selectionKey.isReadable()){
//System.out.println("有讀的來了");
readDataFromChannel(selectionKey);
}
}
}
}
private ByteBuffer buf = ByteBuffer.allocate(1024);
protected void readDataFromChannel(SelectionKey selectionKey) throws IOException {
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
buf.clear();
//buf.flip();取消註釋,單個客戶端發送一條數據,服務器端就無限死循環,輸出“1 1 有讀的來了”;第一個1爲int n的值,第二個1是key.interestOps的值,1代表Readable
int count = 0;
while((count=socketChannel.read(buf))>0){
System.out.println("count:"+count+",buf.size:"+buf.position());
//while(buf.hasRemaining()){
System.out.println("hasRemaining:"+buf.hasRemaining()+",buf.size:"+buf.position());
byte[] data = buf.array();
String str = new String(data);
System.out.println(str);
//}
buf.clear();
}
if (count < 0) {
<span style="white-space:pre"> System.out.println("close the channel...");</span>
socketChannel.close();
}
}
private void sayHello(SocketChannel socketChannel) throws IOException {
buf.clear();
buf.put("hellp!\r\n".getBytes());
buf.flip();
System.out.println("will to send...");
socketChannel.write(buf);
System.out.println("achieve to send...");
buf.clear();
}
private void registerChannel(Selector selector,
SocketChannel socketChannel, int opRead) throws IOException {
if (socketChannel == null) {
return;
}
socketChannel.configureBlocking(false);
socketChannel.register(selector, opRead);
System.out.println("註冊成功——讀");
}
}
public class ClientSocketSelector {
private static final int PORT = 1234;
private static final String IP = "10.20.4.122";
public static void main(String[] args) throws IOException {
new ClientSocketSelector().init(args);
}
public void init(String...args) throws IOException{
Selector selector = Selector.open();
int port = PORT;
String ip = IP;
if(args.length != 0){
ip = args[0];
port = Integer.parseInt(args[1]);
System.out.println(ip);
System.out.println(port);
}
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress("localhost", port));//不能用socketChannel.socket().connect();親身實踐證明!用了就不能正常通信
socketChannel.register(selector, SelectionKey.OP_CONNECT);
while(true){
int n = selector.select();
if (n == 0) {
continue;
}
Iterator it = selector.selectedKeys().iterator();
while(it.hasNext()){
SelectionKey key = (SelectionKey) it.next();
it.remove();
if (key.isConnectable()) {
SocketChannel sc = (SocketChannel) key.channel();
System.out.println("isConnectionPending:"+sc.isConnectionPending());
if (sc.isConnectionPending())
sc.finishConnect();
System.out.println("will to send...");
sc.write(ByteBuffer.wrap("你好".getBytes()));
System.out.println("achieve to send...");
sc.register(selector, SelectionKey.OP_READ);
}
if (key.isReadable()) {
readDataFromChannel(key);
}
}
}
}
private ByteBuffer buf = ByteBuffer.allocate(1024);
protected void readDataFromChannel(SelectionKey key) throws UnsupportedEncodingException, IOException {
SocketChannel sc = (SocketChannel) key.channel();
buf.clear();
if (!sc.isConnected()) {
return;
}
int count = 0;
while((count = sc.read(buf)) > 0){
System.out.println(buf.position());
String str = new String(buf.array());
System.out.println(str);
}
}
}
原本以爲只要一直讓通道處於就緒狀態就能不斷的接收數據(IsReadable),測試後發現,一直處於被選擇的鍵中,不能夠接收到最新的數據。
只有將該鍵從已選擇的鍵中取消,才能重新獲得數據。