JAVA NIO模型的例子 Server和Clinet的通信代码

这篇文章展示了如何使用Java的非阻塞I/O(NIO)来创建一个简单的服务器,该服务器监听特定端口,接收客户端连接,并进行数据交换。客户端程序则负责连接到服务器并发送消息。服务器通过Selector监控多个通道,当通道准备好读取或写入时,进行相应的操作。
摘要由CSDN通过智能技术生成
package com.itproject.project.job.service.impl;

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.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

public class Myserver {
    private int size = 1024;
    private ServerSocketChannel serverSocketChannel;
    private ByteBuffer byteBuffer ;
    private Selector selector;
    private int remoteClientNum = 0;
    public  Myserver(int port){
        try {
            initChannel(port);
        }catch (IOException e){
            e.printStackTrace();
            System.exit(-1);
        }
    }
    //  Channel 得初始化
    public void initChannel(int port) throws IOException {
       //打开Channel
        serverSocketChannel = ServerSocketChannel.open();
        //设置为非阻塞模式
        serverSocketChannel.configureBlocking(false);
        //绑定端口
        serverSocketChannel.bind(new InetSocketAddress(port));
        System.out.println("listener on port: "+port);
        //创建选择器
        selector = Selector.open();
        //想选择器注册通道
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        //分配缓冲区大小
        byteBuffer  = ByteBuffer.allocate(size);


    }

    //监听器,用于监听Channel 上得数据变化
    private  void listener() throws  Exception {
        while (true){
        //返回多少int 类型得数值表示有多少个Channel处于就绪状态
           int n = selector.select();
           if(n==0){
               continue;
           }
           //一个selector对于多个SelectionKey, 一个SelectionKey 对于一个Channel
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();

           while (iterator.hasNext()){
               SelectionKey key = iterator.next();
               //如果SelectionKey 处于连接就绪状态,则开始接受客户端得连接
               if (key.isAcceptable()){
                   //获得channel
                   ServerSocketChannel server = (ServerSocketChannel) key.channel();
                   //channel 接受链接
                   SocketChannel channel = server.accept();

                   //channel 注册
                   registerChannel(selector,channel,SelectionKey.OP_READ);
                   //远程客户端的连接数统计
                   remoteClientNum ++;
                   System.out.println("online client num = "+remoteClientNum);
                   write(channel,"hello client ".getBytes());


               }
               //如果通道已经处在读就绪状态,则读取通道的数据
               if (key.isReadable()){
                   read(key);
               }
               iterator.remove();



           }






        }
    }

    private void read(SelectionKey key) throws IOException {
        SocketChannel socketChannel = (SocketChannel) key.channel();
        int count;
        byteBuffer.clear();
        //从通道读取数据到缓冲区
        while ((count =socketChannel.read(byteBuffer))>0){
            //byteBuffer 从写模式变为读模式
            byteBuffer.flip();
            while (byteBuffer.hasRemaining()){
                System.out.println((char)byteBuffer.get());
            };
            byteBuffer.clear();
        }
        if(count <0){
            socketChannel.close();
        }

    }

    private void write(SocketChannel channel, byte[] writeDate) throws IOException {
        byteBuffer.clear();
        byteBuffer.put(writeDate);
        byteBuffer.flip();
        //将缓冲区的数据写入通道
        channel.write(byteBuffer);
    }


    private void registerChannel(Selector selector, SocketChannel channel, int opRead) throws IOException {
      if (channel == null){
          return;
      }
      channel.configureBlocking(false);
      channel.register(selector,opRead);
    }


    public static void main(String[] args) {
        try {
            Myserver myserver = new Myserver(9999);
            myserver.listener();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}
package com.itproject.project.job.service.impl;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

public class MyClient {
    private int size = 1024;
    private SocketChannel socketChannel;
    private ByteBuffer byteBuffer ;

    public void  connectServer() throws IOException {
       //打开通道
        socketChannel = socketChannel.open();
       //设置连接地址和端口
        socketChannel.connect(new InetSocketAddress("127.0.0.1",9999));
       //设置为非阻塞模式
        socketChannel.configureBlocking(false);

        byteBuffer = ByteBuffer.allocate(size);
        receive();

    }

    private void receive() throws IOException {
        while (true){
            byteBuffer.clear();
            int count;
            //如果没有数据可读,则read方法一直阻塞,置到读取新数据
            while ((count = socketChannel.read(byteBuffer))>0){
                byteBuffer.flip();
                while (byteBuffer.hasRemaining()){
                    System.out.println((char) byteBuffer.get());
                }
                send2Server("say hi".getBytes());
            }
        }
    }

    private void send2Server(byte[] bytes) throws IOException {
        byteBuffer.clear();
        byteBuffer.put(bytes);
        byteBuffer.flip();
        socketChannel.write(byteBuffer);

    }

    public static void main(String[] args) throws IOException {
        new MyClient().connectServer();
    }


}

以上代码可以直接复制拿来测试即可!!谢谢各位!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值