JAVA NIO实现客户端与服务端通信
使用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实现客户端与服务端通信相关推荐
- socket java 客户端_Java基于socket实现的客户端和服务端通信功能完整实例
本文实例讲述了Java基于socket实现的客户端和服务端通信功能.分享给大家供大家参考,具体如下: 以下代码参考马士兵的聊天项目,先运行ChatServer.java实现端口监听,然后再运行Chat ...
- 浅议C#客户端和服务端通信的几种方法:Rest和GRPC和其他
本文来自:https://michaelscodingspot.com/rest-vs-grpc-for-asp-net/ 浅议C#客户端和服务端通信的几种方法:Rest和GRPC 在C#客户端和C# ...
- Java中Socket实现客户端和服务端通信(多线程实现全双工通信)
效果图 目录结构 服务端Server package server;import thread.SocketReader; import thread.SocketWrite;import java. ...
- Java笔记-为客户端及服务端创建公私钥的密钥库
使用密钥库使得客户端与服务器之间进行安全的通信,通过下面的方式生成公钥私钥库: 1. 创建client及server的keystore. 2. 从keystore中导出certificate. 3. ...
- Java--Socket客户端,服务端通信
1.客户端接受服务端的消息并打印: 客户端: import java.io.BufferedReader; import java.io.IOException; import java.io.Inp ...
- 客户端和服务端通信原理
客户端和服务端 客户端:可以向服务端发起请求的,并且接受返回的内容的进行处理 服务器端:能够接受客户端的请求,并且把相关资源信息返回给客户端的 web 服务站点 详细 url 地址解析 DNS 服务器 ...
- java nio 客户端_Java网络编程:Netty框架学习(二)---Java NIO,实现简单的服务端客户端消息传输...
概述 上篇中已经讲到Java中的NIO类库,Java中也称New IO,类库的目标就是要让Java支持非阻塞IO,基于这个原因,更多的人喜欢称Java NIO为非阻塞IO(Non-Block IO), ...
- gPRC简介以及Java中使用gPRC实现客户端与服务端通信(附代码下载)
场景 ProtoBuf的介绍以及在Java中使用protobuf将对象进行序列化与反序列化: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/det ...
- Netty4 学习笔记之一:客户端与服务端通信 demo
前言 因为以前在项目中使用过Mina框架,感受到了该框架的强大之处.于是在业余时间也学习了一下Netty.因为Netty的主要版本是Netty3和Netty4(Netty5已经被取消了),所以我就直接 ...
最新文章
- 在docker中使用MySQL数据库
- ubuntu 16.04 中配置Eclipse c++开发环境
- CodeForces - 1579G Minimal Coverage(dp)
- oc61--block
- Java电商项目-5.内容管理cms系统
- MySQL Clone插件
- jsp写的简单购书网站
- 银联无跳转支付-Token银联侧
- 计算机学报论文字数要求,常见EI学报综述类文章分析
- dede所有目录模板全解
- 【转】Python Enhancement Proposal #8【PEP8】
- 全球云服务商是怎么排名的?国内云主机市场占有率份额排行对比
- urllib库如何设置代理如何传递并保存cookie【python爬虫入门进阶】(02-3)
- python朋友圈自动点赞_基于airtest的朋友圈自动点赞
- 工业相机和镜头选型技巧
- 掌门优课用户量增多,用户看上了它什么?
- 用Python代码来下载任意指定网易云歌曲
- curl模拟发送post请求参数通过json格式传输时需要对引号进行转义
- 小米手机修改ip代理服务器,小米手机如何设置和更改静态IP地址
- htc t328w android4.0,Android4.0新机 HTC T328w仅售1999