System.out.println(new String(byteBuffer.array(),0,num));
byteBuffer.clear();
}
/*// 5.关闭流
fileChannel.close();
socketChannel.close();*/
}
}
服务器代码
public class BlockServer {
/**
-
IO阻塞 服务端
-
@param args
-
@throws Exception
*/
public static void main(String[] args) throws Exception {
//1.获取通道
ServerSocketChannel server = ServerSocketChannel.open();
//2.得到文件通道,将客户端传递的图片写入到本地
FileChannel fileChannel = FileChannel.open(Paths.get(“c:/tools/bb.jpg”),
StandardOpenOption.WRITE
,StandardOpenOption.CREATE);// 如果不存在就创建
// 3.绑定连接
server.bind(new InetSocketAddress(9999));
// 4.获取客户端的连接(阻塞的)
SocketChannel client = server.accept();
// 5.声明Buffer存储图片
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
// 6.将客户端传递的数据保存在本地
while(client.read(byteBuffer)!=-1){
byteBuffer.flip();
fileChannel.write(byteBuffer);
byteBuffer.clear();
}
byteBuffer.put(“图片接收成功!!”.getBytes());
byteBuffer.flip();
client.write(byteBuffer);
byteBuffer.clear();
// 显示的告诉客户端信息输完了
client.shutdownOutput();
/*fileChannel.close();
client.close();
server.close();*/
}
}
======================================================================
如果使用非阻塞模式的话,那么我们就可以不显式告诉服务器已经发完数据了,但是需要显示的指定是非阻塞的
客户端:
public class NoBlockClient {
public static void main(String[] args) throws Exception {
// 1. 获取通道
SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(“127.0.0.1”, 6666));
// 1.1切换成非阻塞模式
socketChannel.configureBlocking(false);
// 2. 发送一张图片给服务端吧
FileChannel fileChannel = FileChannel.open(Paths.get(“c:/tools/a9.jpg”),
StandardOpenOption.READ);
// 3.要使用NIO,有了Channel,就必然要有Buffer,Buffer是与数据打交道的呢
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 4.读取本地文件(图片),发送到服务器
while (fileChannel.read(buffer) != -1) {
// 在读之前都要切换成读模式
buffer.flip();
socketChannel.write(buffer);
// 读完切换成写模式,能让管道继续读取文件的数据
buffer.clear();
}
// 5. 关闭流
fileChannel.close();
socketChannel.close();
}
}
服务器:
public class NoBlockServer {
public static void main(String[] args) throws Exception {
// 1.获取通道
ServerSocketChannel server = ServerSocketChannel.open();
// 2.切换成非阻塞模式
server.configureBlocking(false);
// 3. 绑定连接
server.bind(new InetSocketAddress(6666));
// 4. 获取选择器
Selector selector = Selector.open();
// 4.1将通道注册到选择器上,指定接收“监听通道”事件
server.register(selector, SelectionKey.OP_ACCEPT);
// 5. 轮训地获取选择器上已“就绪”的事件—>只要select()>0,说明已就绪
while (selector.select() > 0) {
// 6. 获取当前选择器所有注册的“选择键”(已就绪的监听事件)
Iterator iterator = selector.selectedKeys().iterator();
// 7. 获取已“就绪”的事件,(不同的事件做不同的事)
while (iterator.hasNext()) {
SelectionKey selectionKey = iterator.next();
// 接收事件就绪
if (selectionKey.isAcceptable()) {
// 8. 获取客户端的链接
SocketChannel client = server.accept();
// 8.1 切换成非阻塞状态
client.configureBlocking(false);
// 8.2 注册到选择器上–>拿到客户端的连接为了读取通道的数据(监听读就绪事件)
client.register(selector, SelectionKey.OP_READ);
} else if (selectionKey.isReadable()) { // 读事件就绪
// 9. 获取当前选择器读就绪状态的通道
SocketChannel client = (SocketChannel) selectionKey.channel();
// 9.1读取数据
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 9.2得到文件通道,将客户端传递过来的图片写到本地项目下(写模式、没有则创建)
FileChannel outChannel = FileChannel.open(Paths.get(“2.png”), StandardOpenOption.WRITE,
StandardOpenOption.CREATE);
while (client.read(buffer) > 0) {
// 在读之前都要切换成读模式
buffer.flip();
outChannel.write(buffer);
// 读完切换成写模式,能让管道继续读取文件的数据
buffer.clear();
}
}
// 10. 取消选择键(已经处理过的事件,就应该取消掉了)
iterator.remove();
}
}
}
}
简单总结一下使用NIO时的要点:
-
将Socket通道注册到Selector中,监听感兴趣的事件
-
当感兴趣的时间就绪时,则会进去我们处理的方法进行处理
-
每处理完一次就绪事件,删除该选择键(因为我们已经处理完了)
=============================================================================
发送方
public static void main(String[] args) throws IOException {
// 获取通道
DatagramChannel dc = DatagramChannel.open();
// 非阻塞的
dc.configureBlocking(false);
ByteBuffer buf = ByteBuffer.allocate(1024);
Scanner scan = new Scanner(System.in);
while(scan.hasNext()){
String str = scan.next();
buf.put((new Date().toString()+“\n”+str).getBytes());
buf.flip();
dc.send(buf, new InetSocketAddress(“127.0.0.1”, 6666));
buf.clear();
}
dc.close();
}
接收方
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
DatagramChannel dc = DatagramChannel.open();
dc.bind(new InetSocketAddress(6666));
dc.configureBlocking(false);
// 获取选择器
Selector selector = Selector.open();
dc.register(selector, SelectionKey.OP_READ);
while(selector.select() > 0){
Iterator it = selector.selectedKeys().iterator();
while(it.hasNext()){
SelectionKey sk = it.next();
if(sk.isReadable()){
ByteBuffer buf = ByteBuffer.allocate(1024);
dc.receive(buf);
buf.flip();
System.out.println(new String(buf.array(),0,buf.limit()));
buf.clear();
}
}
it.remove();
}
}
======================================================================
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-Soweh1P8-1715856912582)]
[外链图片转存中…(img-pTz4aQmA-1715856912582)]
[外链图片转存中…(img-mErH6TEv-1715856912582)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!