使用java NIO实现nio客户端连接nio服务端发送消息

一丶NIO服务端

public static void main(String[] args) {server();}public static void server() {// 创建选择器和socket channeltry (Selector selector = Selector.open();ServerSocketChannel ssc = ServerSocketChannel.open()) {// 绑定端口ssc.socket().bind(new InetSocketAddress(8080));// 设置不阻塞ssc.configureBlocking(false);// socket注册选择器和监听链接事件ssc.register(selector, SelectionKey.OP_ACCEPT);System.out.println("服务启动");while (true) {// 选择器会阻塞到有对应的事件发生selector.select();// 取出发生的事件Iterator<SelectionKey> iter = selector.selectedKeys().iterator();while (iter.hasNext()) {SelectionKey key = iter.next();try {// 连接事件if (key.isAcceptable()) {// 处理连接handleAccept(key);}// 读事件if (key.isReadable()) {// 处理读handleRead(key);}// 写事件且key有效的时候if (key.isWritable() && key.isValid()) {// 处理写handleWrite(key);}} catch (Exception e) {e.printStackTrace();// 发生异常关闭channelkey.channel().close();}// 处理完成后移除该事件iter.remove();}}} catch (Exception e) {e.printStackTrace();}}public static void handleAccept(SelectionKey key) throws IOException {System.out.println("accept 就绪");ServerSocketChannel channel = (ServerSocketChannel) key.channel();// 建立连接SocketChannel sc = channel.accept();// 设置不阻塞sc.configureBlocking(false);// 注册读事件,和添加一个处理数据的ReadWriteBuffer缓存sc.register(key.selector(), SelectionKey.OP_READ, new ReadWriteBuffer());System.out.println(sc.getRemoteAddress() + "连接成功");}public static void handleRead(SelectionKey key) throws IOException {System.out.println("read 就绪");SocketChannel channel = (SocketChannel) key.channel();// 取出建立连接的时候添加的缓存ReadWriteBuffer readWriteBuffer = (ReadWriteBuffer) key.attachment();// 读取数据ByteBuffer readBuffer = readWriteBuffer.readBuffer;int read;StringBuilder sb = new StringBuilder();while ((read = channel.read(readBuffer)) > 0) {readBuffer.flip();byte[] readByte = new byte[read];readBuffer.get(readByte);sb.append(new String(readByte));readBuffer.clear();}System.out.println(sb);// 添加写事件key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);// 随便处理的回复客户端的消息String result = sb.toString().replace("?", "!");result = result.charAt(result.length() - 1) != '!' ? result + "!" : result;// 往buffer中写入数据readWriteBuffer.writeBuffer.put(result.getBytes());// 读取不到数据后把channel关闭if (read == -1) {channel.close();}}public static void handleWrite(SelectionKey key) throws IOException {System.out.println("write 就绪");// 取出buffer进行读取ReadWriteBuffer readWriteBuffer = (ReadWriteBuffer) key.attachment();readWriteBuffer.writeBuffer.flip();SocketChannel sc = (SocketChannel) key.channel();// 有数据的时候将数据写入socket中if (readWriteBuffer.writeBuffer.hasRemaining()) {sc.write(readWriteBuffer.writeBuffer);} else {// 注销写事件key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);}// 将buffer中没有用到的数据进行迁移readWriteBuffer.writeBuffer.compact();}// 申请的bufferstatic class ReadWriteBuffer {// 处理读操作ByteBuffer readBuffer = ByteBuffer.allocateDirect(1024);// 处理写操作ByteBuffer writeBuffer = ByteBuffer.allocateDirect(1024);}

二丶NIO客户端

public static void main(String[] args) {client();}public static void client() {// 单线程池ExecutorService single = Executors.newSingleThreadExecutor();ByteBuffer readBuffer = ByteBuffer.allocateDirect(1024);ByteBuffer writeBuffer = ByteBuffer.allocateDirect(1024);// 开启选择器 socket scanner(用来发送消息)try (Selector selector = Selector.open();SocketChannel sc = SocketChannel.open();Scanner scanner = new Scanner(System.in)) {sc.configureBlocking(false);// 建立连接的地址sc.connect(new InetSocketAddress("localhost", 8080));// 注册连接事件sc.register(selector, SelectionKey.OP_CONNECT);while (true) {selector.select();Iterator<SelectionKey> keys = selector.selectedKeys().iterator();while (keys.hasNext()) {SelectionKey key = keys.next();// 连接事件且连接完成后,注册读事件和写事件if (key.isConnectable()) {if (sc.finishConnect()) {sc.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);}}// 读事件if (key.isReadable()) {// 读取服务端数据readBuffer.clear();int read = sc.read(readBuffer);byte[] readByte = new byte[read];readBuffer.flip();readBuffer.get(readByte);System.out.println(new String(readByte));// 重新注册写事件key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);}// 写事件if (key.isWritable()) {// 使用线程写数据到服务端threadWrite(single, writeBuffer, sc, scanner);// 取消注册写事件(不取消会造成上一次数据可能还没发送,下次进来还会继续执行)key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);}// 移除keykeys.remove();}}} catch (Exception e) {e.printStackTrace();}}private static void threadWrite(ExecutorService single, ByteBuffer writeBuffer, SocketChannel sc, Scanner scanner) {single.execute(() -> {try {// 休眠TimeUnit.SECONDS.sleep(1);// 使用scanner读取控制台输入System.out.println(Thread.currentThread().getName() + "请输入:");String line = scanner.nextLine();writeBuffer.put(line.getBytes());writeBuffer.flip();// 写入数据while (writeBuffer.hasRemaining()) {sc.write(writeBuffer);}writeBuffer.compact();} catch (Exception e) {e.printStackTrace();}});}

实现效果如下:

JAVA NIO实现客户端与服务端通信相关推荐

  1. socket java 客户端_Java基于socket实现的客户端和服务端通信功能完整实例

    本文实例讲述了Java基于socket实现的客户端和服务端通信功能.分享给大家供大家参考,具体如下: 以下代码参考马士兵的聊天项目,先运行ChatServer.java实现端口监听,然后再运行Chat ...

  2. 浅议C#客户端和服务端通信的几种方法:Rest和GRPC和其他

    本文来自:https://michaelscodingspot.com/rest-vs-grpc-for-asp-net/ 浅议C#客户端和服务端通信的几种方法:Rest和GRPC 在C#客户端和C# ...

  3. Java中Socket实现客户端和服务端通信(多线程实现全双工通信)

    效果图 目录结构 服务端Server package server;import thread.SocketReader; import thread.SocketWrite;import java. ...

  4. Java笔记-为客户端及服务端创建公私钥的密钥库

    使用密钥库使得客户端与服务器之间进行安全的通信,通过下面的方式生成公钥私钥库: 1. 创建client及server的keystore. 2. 从keystore中导出certificate. 3. ...

  5. Java--Socket客户端,服务端通信

    1.客户端接受服务端的消息并打印: 客户端: import java.io.BufferedReader; import java.io.IOException; import java.io.Inp ...

  6. 客户端和服务端通信原理

    客户端和服务端 客户端:可以向服务端发起请求的,并且接受返回的内容的进行处理 服务器端:能够接受客户端的请求,并且把相关资源信息返回给客户端的 web 服务站点 详细 url 地址解析 DNS 服务器 ...

  7. java nio 客户端_Java网络编程:Netty框架学习(二)---Java NIO,实现简单的服务端客户端消息传输...

    概述 上篇中已经讲到Java中的NIO类库,Java中也称New IO,类库的目标就是要让Java支持非阻塞IO,基于这个原因,更多的人喜欢称Java NIO为非阻塞IO(Non-Block IO), ...

  8. gPRC简介以及Java中使用gPRC实现客户端与服务端通信(附代码下载)

    场景 ProtoBuf的介绍以及在Java中使用protobuf将对象进行序列化与反序列化: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/det ...

  9. Netty4 学习笔记之一:客户端与服务端通信 demo

    前言 因为以前在项目中使用过Mina框架,感受到了该框架的强大之处.于是在业余时间也学习了一下Netty.因为Netty的主要版本是Netty3和Netty4(Netty5已经被取消了),所以我就直接 ...

最新文章

  1. 在docker中使用MySQL数据库
  2. ubuntu 16.04 中配置Eclipse c++开发环境
  3. CodeForces - 1579G Minimal Coverage(dp)
  4. oc61--block
  5. Java电商项目-5.内容管理cms系统
  6. MySQL Clone插件
  7. jsp写的简单购书网站
  8. 银联无跳转支付-Token银联侧
  9. 计算机学报论文字数要求,常见EI学报综述类文章分析
  10. dede所有目录模板全解
  11. 【转】Python Enhancement Proposal #8【PEP8】
  12. 全球云服务商是怎么排名的?国内云主机市场占有率份额排行对比
  13. urllib库如何设置代理如何传递并保存cookie【python爬虫入门进阶】(02-3)
  14. python朋友圈自动点赞_基于airtest的朋友圈自动点赞
  15. 工业相机和镜头选型技巧
  16. 掌门优课用户量增多,用户看上了它什么?
  17. 用Python代码来下载任意指定网易云歌曲
  18. curl模拟发送post请求参数通过json格式传输时需要对引号进行转义
  19. 小米手机修改ip代理服务器,小米手机如何设置和更改静态IP地址
  20. htc t328w android4.0,Android4.0新机 HTC T328w仅售1999

热门文章

  1. 微信小程序搭建新闻列表(跟进上一篇博客案例)
  2. 【机器学习笔记之五】用ARIMA模型做需求预测用ARIMA模型做需求预测
  3. Apache 错误日记(Error Log)记录分析
  4. matlab在线性系统中的应用,MATLAB在控制系统仿真中的应用
  5. 操作系统 CentOS8 Linux内核编译一遍通过教程
  6. 华硕天选2/系列切换应用声音消失问题的解决方法
  7. 网络层(三)构成超网
  8. python的pyautogui的函数,实现按键精灵
  9. 八字四柱排盘原理及源码(PHP、Java和Python)
  10. Java秘史——名字的来历