基于nio的ScoktChannel数据传输

java中nio的ScoktChannel数据传输

1.服务端server

package com.netty.redis.zookeeper.netty.unit1.oneday;

import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

/**
 * @Description: ScoktChannelServer服务端
 * @ClassName: ScoktChannelServer
 * @Author zhaomx
 * @Version 1.0
 * @Date 2021-07-12 17:31
 */
@Slf4j
public class ScoktChannelServer {

    public static void main(String[] args) throws IOException {
        socketChannelServer();
    }

    public static void socketChannelServer() throws IOException {
        //1.创建一个ServerSocketChannel对象,使用open方法打开套接字通道
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //2.绑定host和端口
        serverSocketChannel.socket().bind(new InetSocketAddress("localhost", 4444));
        //3.通过ServerScoketChannel的accept方法生成ScoketChannel用户对象,从客户端读/写数据
        SocketChannel socketChannel = serverSocketChannel.accept();
        //4.创建写数据的缓存区对象
        ByteBuffer writeBuffer = ByteBuffer.allocate(128);
        writeBuffer.put("hello client this is from server -_-".getBytes("UTF-8"));
        //4.1把读取的数据写入到输出通道中,相当于从缓冲区中读取数据,将writeBuffer从写模式变为读模式
        //把limit设置为当前的position值,2. 把position设置为0
        writeBuffer.flip();
        socketChannel.write(writeBuffer);

        //5.创建读数据的缓存区对象
        ByteBuffer readBuffer = ByteBuffer.allocate(128);
        socketChannel.read(readBuffer);
        //5.1把读取的数据写入到输出通道中,相当于从缓冲区中读取数据,将writeBuffer从写模式变为读模式
        readBuffer.flip();

        StringBuilder stringBuilder = new StringBuilder();
        while (readBuffer.hasRemaining()) {
            stringBuilder.append((char) readBuffer.get());
        }
        log.info("从客户端接受:{}", stringBuilder.toString());
        socketChannel.close();
        serverSocketChannel.close();
    }

    public void old(){
        try {
            //1.通过ServerSocketChannel 的open()方法创建一个ServerSocketChannel对象,open方法的作用:打开套接字通道
            ServerSocketChannel ssc = ServerSocketChannel.open();
            //2.通过ServerSocketChannel绑定ip地址和port(端口号)
            ssc.socket().bind(new InetSocketAddress("127.0.0.1", 3333));
            //通过ServerSocketChannelImpl的accept()方法创建一个SocketChannel对象用户从客户端读/写数据
            SocketChannel socketChannel = ssc.accept();
            //3.创建写数据的缓存区对象
            ByteBuffer writeBuffer = ByteBuffer.allocate(128);
            writeBuffer.put("hello WebClient this is from WebServer".getBytes());
            writeBuffer.flip();
            socketChannel.write(writeBuffer);
            //创建读数据的缓存区对象
            ByteBuffer readBuffer = ByteBuffer.allocate(128);
            //读取缓存区数据
            socketChannel.read(readBuffer);
            StringBuilder stringBuffer = new StringBuilder();
            //4.将Buffer从写模式变为可读模式
            readBuffer.flip();
            while (readBuffer.hasRemaining()) {
                stringBuffer.append((char) readBuffer.get());
            }
            System.out.println("从客户端接收到的数据:" + stringBuffer);
            socketChannel.close();
            ssc.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

2.客户端client

package com.netty.redis.zookeeper.netty.unit1.oneday;

import lombok.extern.slf4j.Slf4j;

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

/**
 * @Description: 使用 SocketChannel 传输文件
 * 非阻塞客户端在发起连接后,需要不断的自旋,检测连接是否完成的。
 * SocketChannel 传输通道的 read 读取方法、write 写入方法。
 * 在 SocketChannel 传输通道关闭前,尽量发送一个输出结束标志到对方端。
 * @ClassName: ScoktChannel
 * @Author zhaomx
 * @Version 1.0
 * @Date 2021-07-12 17:24
 */
@Slf4j
public class ScoktChannelClient {

    public static void main(String[] args) throws IOException {
        //1.通过SocketChannel的open()方法创建一个SocketChannel对象
        SocketChannel socketChannel = SocketChannel.open();
        //2.连接到远程服务器(连接此通道的socket)
        socketChannel.connect(new InetSocketAddress("localhost", 4444));
        // 3.创建写数据缓存区对象
        ByteBuffer writeBuffer = ByteBuffer.allocate(128);
        writeBuffer.put("hello WebServer this is from WebClient -_-".getBytes("UTF-8"));
        writeBuffer.flip();
        socketChannel.write(writeBuffer);
        //创建读数据缓存区对象
        ByteBuffer readBuffer = ByteBuffer.allocate(128);
        socketChannel.read(readBuffer);
        //String 字符串常量,不可变;StringBuffer 字符串变量(线程安全),可变;StringBuilder 字符串变量(非线程安全),可变
        StringBuilder stringBuffer = new StringBuilder();
        //4.将Buffer从写模式变为可读模式
        readBuffer.flip();
        while (readBuffer.hasRemaining()) {
            stringBuffer.append((char) readBuffer.get());
        }
        System.out.println("从服务端接收到的数据:" + stringBuffer);

        socketChannel.close();
    }
}

上一篇:Java NIO 基本介绍


下一篇:Java NIO直接缓冲区与非直接缓冲区区别