NIO之完成网络通信

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();*/

}

}

NIO非阻塞形态

======================================================================

如果使用非阻塞模式的话,那么我们就可以不显式告诉服务器已经发完数据了,但是需要显示的指定是非阻塞的

客户端:

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时的要点:

  1. 将Socket通道注册到Selector中,监听感兴趣的事件

  2. 当感兴趣的时间就绪时,则会进去我们处理的方法进行处理

  3. 每处理完一次就绪事件,删除该选择键(因为我们已经处理完了)

DatagramChannel

=============================================================================

发送方

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

}

}

管道(Pipe)

======================================================================

最后

自我介绍一下,小编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开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值