0、java nio编程比较复杂,坑多。可以看一些文章,如nio通道-几个注意点,SocketChannel续2-各种注意点。
1、go语言需要nio吗? go支持协程,所以在代码层面,就是顺序编程,就像阻塞IO一样,一台机器起几万个协程。但其底层实现也是非阻塞的,和java一样,都是epoll
2、用一个聊天室的例子学习一下java nio
package gaofeng.nio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Channel;
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.util.Iterator;
public class Server {
private Charset charset = Charset.forName("UTF-8");
public static void main(String[] args) throws IOException {
new Server().start();
}
public void start() throws IOException {
Selector selector = Selector.open();
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.bind(new InetSocketAddress(8088));
serverChannel.configureBlocking(false);
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("服务端开始监听8080端口...");
while(true){
if(selector.select()==0){
System.out.println("selector.select()==0");
continue;
}
for (Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); iterator.hasNext();) {
SelectionKey key = iterator.next();
iterator.remove();
if(key.isAcceptable()){
SocketChannel oneSocket = serverChannel.accept();
System.out.println("one user:" + oneSocket.getRemoteAddress());
oneSocket.configureBlocking(false);
oneSocket.register(selector, SelectionKey.OP_READ);
oneSocket.write(charset.encode("请输入您的昵称:"));
}if(key.isReadable()){
ByteBuffer buff = ByteBuffer.allocate(1024);
SocketChannel oneSocket = (SocketChannel) key.channel();
try{
while(oneSocket.read(buff)>0){
System.out.print("---");
}
buff.flip();
String info = charset.decode(buff).toString();
System.out.println(oneSocket.getRemoteAddress() + " info:"+info);
if(info.endsWith("%#%")){
broadcast(selector,oneSocket,info.substring(0, info.length()-"%#$".length())+"进入了房间");
}else{
broadcast(selector,oneSocket,info.replace("%#%", "说:"));
}
}catch(Exception e){
key.cancel();
oneSocket.close();
e.printStackTrace();
}
}
}
}
}
private void broadcast(Selector selector,SocketChannel self,String info){
for (SelectionKey key : selector.keys()) {
Channel channel = key.channel();
if(channel instanceof SocketChannel && channel!=self){
try {
System.out.println("broadcast:" + info);
((SocketChannel)channel).write(charset.encode(info));
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
package gaofeng.nio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Scanner;
public class Client {
private String username = null;
private Charset charset = Charset.forName("UTF-8");
public static void main(String[] args) throws IOException {
new Client().start();
}
public void start() throws IOException {
final Selector selector = Selector.open();
SocketChannel socket = SocketChannel.open(new InetSocketAddress("127.0.0.1", 8088));
socket.configureBlocking(false);
socket.register(selector, SelectionKey.OP_READ);
new Thread(){
public void run(){
while(true){
try {
if(selector.select()==0){
System.out.println("selector.select()==0");
continue;
}
} catch (IOException e) {
e.printStackTrace();
}
for (Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); iterator.hasNext();) {
SelectionKey key = iterator.next();
iterator.remove();
if(key.isReadable()){
ByteBuffer buff = ByteBuffer.allocate(1024);
SocketChannel oneSocket = (SocketChannel) key.channel();
try{
while(oneSocket.read(buff)>0){
System.out.print("---");
}
buff.flip();
String info = charset.decode(buff).toString();
System.out.println(info);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
}
}.start();
Scanner scan = new Scanner(System.in);
while(scan.hasNextLine()){
String line = scan.nextLine();
if(line.isEmpty()){
System.out.println(line.isEmpty());
continue;
}
if("exit".equals(line)){
break;
}
String info;
if(username==null){
username=line;
info = username+"%#%";
}else{
info = username+"%#%"+line;
}
socket.write(charset.encode(info));
}
scan.close();
System.out.println("exit");
System.exit(0);
}
}