前某个星期用java的阻塞式io写了一个socket的程序后,感觉用来玩玩还可以,连接量一上来就完了。
然后又看到推荐说nio,就一直想着学学,结果中间这几天考试复习给耽搁了。正好今天没什么考试了,就找时间学了学。
nio网上讲的也挺多的了,我也没必要班门弄斧,就是说说自己的理解吧。

在nio中比较重要的是channel、buffer以及selector这几个东西。
channel跟io的流有点相似,buffer就是缓存区了。selector就是异步用的了。
借用一个人的[神总结][],

Channel对应以前的流,Buffer不是什么新东西,Selector是因为nio可以使用异步的非堵塞模式才加入的东西。
以前的流总是堵塞的,一个线程只要对它进行操作,其它操作就会被堵塞,也就相当于水管没有阀门,你伸手接水的时候,不管水到了没有,你就都只能耗在接水(流)上。

nio的Channel的加入,相当于增加了水龙头(有阀门),虽然一个时刻也只能接一个水管的水,但依赖轮换策略,在水量不大的时候,各个水管里流出来的水,都可以得到妥善接纳,这个关键之处就是增加了一个接水工,也就是Selector,他负责协调,也就是看哪根水管有水了的话,在当前水管的水接到一定程度的时候,就切换一下:临时关上当前水龙头,试着打开另一个水龙头(看看有没有水)。
当其他人需要用水的时候,不是直接去接水,而是事前提了一个水桶给接水工,这个水桶就是Buffer。也就是,其他人虽然也可能要等,但不会在现场等,而是回家等,可以做其它事去,水接满了,接水工会通知他们。
这其实也是非常接近当前社会分工细化的现实,也是统分利用现有资源达到并发效果的一种很经济的手段,而不是动不动就来个并行处理,虽然那样是最简单的,但也是最浪费资源的方式。

相对于网上讲其他的复杂的解释这个更容易理解一点。
继续套用那个例子的话,阻塞式io就是相当于如果多个水龙头来水(多个用户加入),就得多请几个节水工(开多个线程),这就导致花销大啦(系统多开资源)。
具体的关于程序的编写也不再多说啦。我也是看的一知半解的。
还是有问题存在。比如
<font color="red">客户端要发送多个数据的话或者是服务器要一直接受的话,就处理不了,只能一接一发。</font>
这个仍然没想到解决方法。或许是逻辑哪出问题了吧。
直接上程序吧.这个是服务器端的。

package top.txiner.nio;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
/**
 * Created by hundred on 2015/12/20.
 */
public class ServerNIO {
    public static final InetSocketAddress ADDRESS = new InetSocketAddress(8080);
    public Selector selector = null;
    static int BLOCK = 1024;
    private ByteBuffer receiveBuffer = ByteBuffer.allocate(BLOCK);
    private ByteBuffer sendBuffer = ByteBuffer.allocate(BLOCK);
    public ServerNIO() {
        try {
            ServerSocketChannel channel = null;
            channel = ServerSocketChannel.open();
            channel.configureBlocking(false);
            ServerSocket serverSocket = channel.socket();
            serverSocket.bind(ADDRESS);
            selector = Selector.open();
            channel.register(selector, SelectionKey.OP_ACCEPT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        ServerNIO serverNIO = new ServerNIO();
        serverNIO.listen();
    }
    private void listen() {
        Iterator iter = null;
        while (true) {
            try {
                selector.select();
                iter = selector.selectedKeys().iterator();
                while (iter.hasNext()) {
                    SelectionKey key = (SelectionKey) iter.next();
                    iter.remove();
                    handle(key);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    private void handle(SelectionKey key) {
        String receiveText;
        String sendText;
        int count = 0;
        SocketChannel channel = null;
        if (key.isAcceptable()) {
            try {
                ServerSocketChannel serverSocketChannel =
                        (ServerSocketChannel) key.channel();
                channel = serverSocketChannel.accept();
                channel.configureBlocking(false);
                channel.register(selector, SelectionKey.OP_READ);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else if (key.isReadable()) {
            try {
                channel = (SocketChannel) key.channel();
                receiveBuffer.clear();
                count = channel.read(receiveBuffer);
                if (count > 0) {
                    receiveText = new String(receiveBuffer.array(), 0, count);
                    System.out.println("data from client: " + receiveText);
                    channel.register(selector, SelectionKey.OP_WRITE);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else if (key.isWritable()) {
            try {
                sendBuffer.clear();
                channel = (SocketChannel) key.channel();
                BufferedReader br = new BufferedReader(new InputStreamReader
                        (System.in));
                sendText = br.readLine();
                sendBuffer.put(sendText.getBytes());
                sendBuffer.flip();
                channel.write(sendBuffer);
                channel.register(selector, SelectionKey.OP_READ);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

这个是客户端的。

package top.txiner.nio;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
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.util.Iterator;
/**
 * Created by hundred on 2015/12/20.
 */
public class ClientNIO {
    public Selector selector = null;
    static int BLOCK = 1024;
    public int ID = 0;
    private ByteBuffer receiveBuffer = ByteBuffer.allocate(BLOCK);
    private ByteBuffer sendBuffer = ByteBuffer.allocate(BLOCK);
    public static final InetSocketAddress ADDRESS = new InetSocketAddress
            ("localhost", 8080);
    public ClientNIO() {
        try {
            SocketChannel channel = SocketChannel.open();
            channel.configureBlocking(false);
            channel.connect(ADDRESS);
            selector = Selector.open();
            channel.register(selector, SelectionKey.OP_CONNECT);
            ID = (int) (Math.random() * 10);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        ClientNIO clientNIO = new ClientNIO();
        clientNIO.send();
    }
    private void send() {
        int count = 0;
        SelectionKey key = null;
        SocketChannel channel = null;
        String noticeMsg = "connect with you now.I am the " + ID;
        String receiveText;
        String sendText;
        while (true) {
            try {
                selector.select();
                Iterator iter = selector.selectedKeys().iterator();
                while (iter.hasNext()) {
                    key = (SelectionKey) iter.next();
                    if (key.isConnectable()) {
                        System.out.println("connect to server");
                        channel = (SocketChannel) key.channel();
                        if (channel.isConnectionPending()) {
                            channel.finishConnect();
                            sendBuffer.clear();
                            sendBuffer.put(noticeMsg.getBytes());
                            sendBuffer.flip();
                            channel.write(sendBuffer);
                        }
                        channel.configureBlocking(false);
                        channel.register(selector, SelectionKey.OP_READ);
                    } else if (key.isReadable()) {
                        channel = (SocketChannel) key.channel();
                        receiveBuffer.clear();
                        count = channel.read(receiveBuffer);
                        if (count > 0) {
                            receiveText = new String(receiveBuffer.array(),
                                    0, count);
                            System.out.println("data from server: " +
                                    receiveText);
                            channel.register(selector, SelectionKey.OP_WRITE);
                        }
                    } else if (key.isWritable()) {
                        channel = (SocketChannel) key.channel();
                        sendBuffer.clear();
                        BufferedReader br = new BufferedReader(new
                                InputStreamReader(System.in));
                        sendText = br.readLine();
                        sendBuffer.put(sendText.getBytes());
                        sendBuffer.flip();
                        channel.write(sendBuffer);
                        channel.register(selector, SelectionKey.OP_READ);
                    }
                }
                selector.selectedKeys().clear();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

在学nio的时候参考太多了,也没记录,就不付具体参考的了。
如果以后能改得了上面那个问题就再改程序。
数字信号处理考试好难,好多都不会做,没心情在往下瞎编了。

java socket

发表新评论