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();
}
}