网络编程三

NIO之通道
分类:
    客户端通道
            连接服务端
            传递缓冲区(传递数据)
            打开通道  SocketChannel
            连接服务端(指定IP和端口号) InetSocketAddress
            将缓冲区写到服务器  write
            释放资源  close
    代码实现:
          

 public class test {
                public static void main(String[] args) throws IOException {
                    //打开通道
                    SocketChannel open = SocketChannel.open();
                    //指定IP和端口号
                    open.connect(new InetSocketAddress("127.0.0.1",1024));
                    //写出数据
                    ByteBuffer wrap = ByteBuffer.wrap("hello".getBytes());
                    open.write(wrap);
                    //释放资源
                    open.close();
                }
            }



    服务端通道
            服务端通道之负责连接,不负责传输数据
                1.打开一个服务端通道
                2.绑定相应的端口号
                3.通道默认是阻塞的,需要设置为非阻塞
                4.现在没有选择器的加入,服务端需要不定时看下有没有数据发来
                5.如果客户端发来数据了,则在服务端的通道内部,在创建一个客户端通道,相当于是客户端通道的延申
                6.客户端将缓冲区通过通道传递给服务端
                7.服务端创建一个空的缓冲区装数据并输出
            客户端通道连接服务端,并传输数据
            缓冲区,客户端发送的数据都在缓冲区中
            服务端通道内部创建出来的客户端通道,相当于客户端通道的延申,用来传递数据
                代码实现:
                      

 public class NioServer {
                                public static void main(String[] args) throws IOException {
                            //        1.打开一个服务端通道
                                    ServerSocketChannel open = ServerSocketChannel.open();
                            //        2.绑定相应的端口号
                                    ServerSocketChannel bind = open.bind(new InetSocketAddress(1024));
                            //        3.通道默认是阻塞的,需要设置为非阻塞
                                    //如果传递一个true  表示通道为阻塞通道。。。默认值
                                    //如果传递一个false,表示通道为非阻塞通道
                                    open.configureBlocking(false);
                            //        4.现在没有选择器的加入,服务端需要不定时看下有没有数据发来
                                    while (true) {
                                        //        5.如果客户端发来数据了,则在服务端的通道内部,在创建一个客户端通道,相当于是客户端通道的延申
                                        //此时设置了通道非阻塞,如果有客户端来连接,则在服务端通道内部,在创建一个客户端通道,相当于客户端通道延申
                                        //如果调用方法的时候,没有客户端来接连,那么他会返回一个null
                                        SocketChannel accept = open.accept();
                                        if (open!=null){
                                            //        6.客户端将缓冲区通过通道传递给服务端
                                            //        7.服务端创建一个空的缓冲区装数据并输出
                                            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                                            //获取传递过来的数据,并把他们放到byteBuffer缓冲区中
                                                    //返回值:正数,表示本次督导的有效字节个数
                                                    //0:本次没有读到有效字节
                                                    //-1表述读到了末尾
                                            int read = accept.read(byteBuffer);
                                            System.out.println(new String(byteBuffer.array(),0,read));
                                            accept.close();
                                        }
                                    }
                                }
                            }


        练习:客户端发送数据给服务端,服务端接收会返回一个数据给客户端
            
            代码:
                服务端:
              

 public class NioServer {
                    public static void main(String[] args) throws IOException {
                        ServerSocketChannel open = ServerSocketChannel.open();
                        ServerSocketChannel bind = open.bind(new InetSocketAddress(1024));
                        open.configureBlocking(false);
                        while (true){
                            SocketChannel accept = open.accept();
                            if (accept !=null){
                                System.out.println("此时有客户端来连接了");
                                //第二种方法  把延申通道也设置称为非阻塞的
                                accept.configureBlocking(false);
                                //获取客户端传来的数据,并把数据放在byteBuffer1这个缓冲区中
                                ByteBuffer allocate = ByteBuffer.allocate(1024);
                                //不能只读取一次  用循环
                                //accept.read(allocate);
                                int len;
                                //针对缓冲区来说  获取数据  flip方法   添加数据 clear
                                while ((len=accept.read(allocate))>0){
                                    allocate.flip();
                                    System.out.println(new String(allocate.array(),0,len));
                                    allocate.clear();
                                }
                                System.out.println("接收数据完毕,回写一份数据");
                                ByteBuffer wrap = ByteBuffer.wrap("这是返回的数据".getBytes());
                                accept.write(wrap);
                                accept.close();
                            }
                        }
                    }
                }


                客户端代码:
              

 public class NioClient {
                    public static void main(String[] args) throws IOException {
                        SocketChannel open = SocketChannel.open();
                        open.bind(new InetSocketAddress("127.0.0.1", 1024));
                
                        ByteBuffer wrap = ByteBuffer.wrap("这是传往服务端的内容".getBytes());
                        open.write(wrap);
                        //没有结束标记的话 就会一直卡死循环
                        open.shutdownOutput();
                        System.out.println("数据已经传往服务器");
                
                        ByteBuffer allocate = ByteBuffer.allocate(1024);
                        int len;
                        while ((len=open.read(allocate))!=-1){
                            allocate.flip();
                            System.out.println(new String(allocate.array(),0,len));
                            allocate.clear();
                        }
                        open.close();
                    }
                }


        NIO之选择器
            作用:监视通道的状态
                Selector  选择器对象
                SelectionKey  绑定的Key
                SelectableChannel  能使用的选择器通道
                        SocketChannel
                        ServerSocketChannel
            一个服务端对应一个客户端
                1.打开一个服务端通道
                2.绑定对应的端口
                3.通道默认是阻塞的,需要设置为非阻塞
                4.打开一个选择器
                5.如果有客户端来连接了,选择器就告诉服务端通道来连接
                6.在服务端通道内部,在创建一个客户端通道,相当于是客户端通道的延申
                7.如果客户端通道传递数据了,选择器就告诉延申的客户端通道来传输
            如果一个服务端有多个客户端来连接,就会看哪一个服务端通道准备好了,就会让谁去连接
        
        选择器改写服务端
                选择器监视客户端通道
                选择器监视服务端通道
                选择器监视客户端延申通道
            客户端代码:
            

public class NioClient {
    public static void main(String[] args) throws IOException {
        SocketChannel open = SocketChannel.open();
         open.bind(new InetSocketAddress("127.0.0.1", 1024));

        ByteBuffer wrap = ByteBuffer.wrap("这是传往服务端的内容".getBytes());
        open.write(wrap);
        //没有结束标记的话 就会一直卡死循环
        open.shutdownOutput();
        System.out.println("数据已经传往服务器");

        ByteBuffer allocate = ByteBuffer.allocate(1024);
        int len;
        while ((len=open.read(allocate))!=-1){
            allocate.flip();
            System.out.println(new String(allocate.array(),0,len));
            allocate.clear();
        }
        open.close();
    }
}

        服务端代码:
      

 public class NioServer {
    public static void main(String[] args) throws IOException {
       //打开服务端通道
        ServerSocketChannel opServerSocketChannelen = ServerSocketChannel.open();
        //2.选择端口
        ServerSocketChannel bind = opServerSocketChannelen.bind(new InetSocketAddress(1024));
        //设置为非阻塞
        opServerSocketChannelen.configureBlocking(false);
        //选一个选择器
        //Selector ---选择器
        //SelectionKey  -- 绑定通道后返回的key
        //SelectableChannel---可以使用选择器的通道
        Selector selector = Selector.open();
        //绑定选择器和服务端的通道
        opServerSocketChannelen.register(selector,SelectionKey.OP_ACCEPT);
        //选择器会监视客户端通道的状态
        while (true){
            //选择器会监视客户端的状态
            //返回值就表示此时有多少个客户端来连接
            int count = selector.select();
            if (count!=0){
                System.out.println("有客户端来连接了");
                //遍历所有的服务端通道,看哪一个准备号了,谁就会去连接
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                while (iterator.hasNext()){
                    //neselectionKeyxt 一次表示每一个服务端的令牌
                    SelectionKey selectionKey = iterator.next();
                    if (selectionKey.isAcceptable()){
                        //可以通过令牌来获得一个已经就绪的服务端通道
                        ServerSocketChannel channel = (ServerSocketChannel)selectionKey.channel();
                        //客户端的延申通道
                        channel.accept();
                        //将客户端的延申通道改为非阻塞的
                        channel.configureBlocking(false);
                        channel.register(selector,SelectionKey.OP_READ);
                        //当客户端来连接的时候,所有的步骤已经执行完毕
                    }else if (selectionKey.isAcceptable()){
                        //当前通道以及做好了读取的准备(延申通道)
                        SocketChannel channel = (SocketChannel) selectionKey.channel();
                        ByteBuffer allocate = ByteBuffer.allocate(1024);
                        //channel.read(allocate);
                        int len;
                        while ((len=channel.read(allocate))>0){
                            allocate.flip();
                            System.out.println(new String(allocate.array(),0,len));
                            allocate.clear();
                        }
                        //给客户端的回写数据
                        channel.write(ByteBuffer.wrap("这是给客户端回写的数据".getBytes(StandardCharsets.UTF_8)));
                        channel.close();
                    }
                    iterator.remove();
                }
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值