【学习笔记】Socket NIO demo
来源:互联网 发布:安装 SQL 2014 编辑:程序博客网 时间:2024/05/17 01:04
模拟场景
客户端请求连接服务端,并发送消息,服务端收到消息后返回信息给客户端,当客户端关闭时,服务端停止socketChannel,
当服务端关闭时,客户端也相应关闭
服务端
package nio;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.util.Iterator;import java.util.Set;/** * Created by zansha on 17/10/19. */public class TCPServer { // 缓冲区大小 private static final int BufferSize = 1024; // 超时时间,单位毫秒 private static final int TimeOut = 3000; // 本地监听端口 private static final int ListenPort = 1978; public static void main(String[] args) throws IOException, InterruptedException { Selector selector = Selector.open(); ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.socket().bind(new InetSocketAddress(ListenPort)); serverSocketChannel.configureBlocking(false); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); TCPProtocol protocol = new TCPProtocolImpl(BufferSize); while (true){ int keys = selector.select(TimeOut); if (keys==0){ continue; } Set<SelectionKey> selectionKeySet = selector.selectedKeys(); Iterator<SelectionKey> selectionKeys = selectionKeySet.iterator(); while (selectionKeys.hasNext()){ SelectionKey selectionKey = selectionKeys.next(); selectionKeys.remove(); try { if (selectionKey.isAcceptable()){ System.out.println("acceptable op...."); protocol.handleAccept(selectionKey); } // 从客户端读取数据 if (selectionKey.isReadable()){ protocol.handleRead(selectionKey); } }catch (Exception e){ if (selectionKey!=null){ selectionKey.cancel(); if (selectionKey.channel()!=null){ selectionKey.channel().close(); } } } } } }}
package nio;import java.io.IOException;import java.nio.channels.SelectionKey;/** * Created by zansha on 17/10/19. */public interface TCPProtocol { /** * 接收一个SocketChannel的处理 * * @param key * @throws IOException */ void handleAccept(SelectionKey key) throws IOException; /** * 从一个SocketChannel读取信息的处理 * * @param key * @throws IOException */ void handleRead(SelectionKey key) throws IOException; /** * 向一个SocketChannel写入信息的处理 * * @param key * @throws IOException */ void handleWrite(SelectionKey key) throws IOException;}
package nio;import java.io.IOException;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.nio.charset.Charset;import java.text.SimpleDateFormat;import java.util.Date;import java.util.LinkedHashMap;/** * Created by zansha on 17/10/19. */public class TCPProtocolImpl implements TCPProtocol { private int bufferSize; public TCPProtocolImpl(int bufferSize) { this.bufferSize = bufferSize; } /** * 将可连接 调整为 可读取 */ public void handleAccept(SelectionKey key) throws IOException { SocketChannel clientChannel = ((ServerSocketChannel) key.channel()).accept(); clientChannel.configureBlocking(false); clientChannel.register(key.selector(), SelectionKey.OP_READ, ByteBuffer.allocate(bufferSize)); } public void handleRead(SelectionKey key) throws IOException { // 获得与客户端通信的信道 SocketChannel clientChannel = (SocketChannel) key.channel(); // 得到并清空缓冲区 ByteBuffer buffer = (ByteBuffer) key.attachment(); buffer.clear(); // 读取信息获得读取的字节数 long bytesRead = clientChannel.read(buffer); if (bytesRead == -1) { // 没有读取到内容的情况 clientChannel.close(); } else { // 将缓冲区准备为数据传出状态 buffer.flip(); // 将字节转化为为UTF-16的字符串 String receivedString = Charset.forName("UTF-16").newDecoder().decode(buffer).toString(); // 控制台打印出来 System.out.println("客户端信息:" + receivedString); // 准备发送的文本 String sendString = "服务端消息:已收到消息"+receivedString; buffer = ByteBuffer.wrap(sendString.getBytes("UTF-16")); clientChannel.write(buffer); // 设置为下一次读取或是写入做准备 key.interestOps(SelectionKey.OP_READ); } } public void handleWrite(SelectionKey key) throws IOException { }}
客户端
package nio;import java.io.IOException;import java.io.UnsupportedEncodingException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.ClosedChannelException;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.SocketChannel;/** * Created by zansha on 17/10/19. */public class TCPClient { //信道选择器 private Selector selector; // 与服务器通信的信道 SocketChannel socketChannel; // 要连接的服务器Ip地址 private String hostIp; // 要连接的远程服务器在监听的端口 private int hostListenningPort; /** * 构造函数 * * @param HostIp * @param HostListenningPort * @throws IOException */ public TCPClient(String HostIp, int HostListenningPort) throws IOException { this.hostIp = HostIp; this.hostListenningPort = HostListenningPort; initialize(); } /** * 初始化 * * @throws IOException */ private void initialize() throws IOException { // 打开监听信道并设置为非阻塞模式 socketChannel = SocketChannel.open(new InetSocketAddress(hostIp, hostListenningPort)); socketChannel.configureBlocking(false); // 打开并注册选择器到信道 selector = Selector.open(); socketChannel.register(selector,SelectionKey.OP_READ); // 启动读取线程 TCPClientReadThread tcpClientReadThread = new TCPClientReadThread(selector); new Thread(tcpClientReadThread).start(); } /** * 发送字符串到服务器 * * @param message * @throws IOException */ public void sendMsg(String message) throws IOException{ ByteBuffer writeBuffer; try { Thread.sleep(2000); writeBuffer = ByteBuffer.wrap(message.getBytes("UTF-16")); socketChannel.write(writeBuffer); socketChannel.register(selector,SelectionKey.OP_READ); } catch (InterruptedException e) { e.printStackTrace(); }catch (UnsupportedEncodingException e) { e.printStackTrace(); } } public static void main(String[] args) throws IOException { TCPClient client = new TCPClient("localhost", 1978); for(int i=0; i<50; i++){ try { client.sendMsg("Nio" + i); } catch (IOException e) { break; } } System.out.println("客户端发信息结束"); TCPClientReadThread.run=false; }}
package nio;import java.io.IOException;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.SocketChannel;import java.nio.charset.Charset;import java.util.Iterator;import java.util.Set;import java.util.concurrent.atomic.AtomicBoolean;/** * Created by zansha on 17/10/19. */public class TCPClientReadThread implements Runnable { private Selector selector; public static boolean run = true; public TCPClientReadThread(Selector selector) { this.selector = selector; } @Override public void run() { while (run){ try { int keys = selector.select(3000); if (keys==0){ continue; } Set<SelectionKey> selectionKeySet = selector.selectedKeys(); Iterator<SelectionKey> selectionKeys = selectionKeySet.iterator(); while (selectionKeys.hasNext()) { SelectionKey selectionKey = selectionKeys.next(); selector.selectedKeys().remove(selectionKey); if (selectionKey.isReadable()) { SocketChannel socketChannel = (SocketChannel) selectionKey.channel(); ByteBuffer buffer = ByteBuffer.allocate(1024); long bytesRead = socketChannel.read(buffer); if (bytesRead==-1){ socketChannel.close(); }else { buffer.flip(); // 将字节转化为为UTF-16的字符串 String receivedString = Charset.forName("UTF-16").newDecoder().decode(buffer).toString(); // 控制台打印出来 System.out.println(receivedString); // 为下一次读取作准备 selectionKey.interestOps(SelectionKey.OP_READ); } } } } catch (IOException ex) { try { selector.close(); break; } catch (IOException e) { e.printStackTrace(); } } } System.out.println("客户端关闭"); }}
阅读全文
0 0
- 【学习笔记】Socket NIO demo
- NIO Socket Server DEMO
- 【学习笔记】socket IO demo
- Java NIO 学习demo
- NIO学习demo
- [Erlang 学习笔记] erlang socket 小小 demo
- nio socket 学习
- NIO Socket学习
- 学习socket nio
- Java NIO 同步非阻塞Socket DEMO
- java nio学习之 socket+nio 通信
- 学习socket nio 之ByteBuffer
- (socket-nio-netty学习-1)socket,NIO,AIO基本概念
- Java Nio学习笔记
- NIO学习笔记
- NIO学习笔记(一)
- NIO学习笔记1
- Java NIO学习笔记
- [linux-shell]crontab的介绍和使用(linux的定时)
- 推荐系统评测指标—准确率(Precision)、召回率(Recall)、F值(F-Measure)
- ros发布gps定位信息
- 数论基础
- Spring Boot 配置文件和日志文件放到jar之外
- 【学习笔记】Socket NIO demo
- Android使用系统API进行音视频编码
- Maven项目tomcat:run的方式运行取不到classpath目录下配置文件
- CSS样式小知识点
- 导出pdf之--终于完成
- 以删除重建的方式修复托管磁盘虚拟机
- 自定义控件那些事儿 ----- 二
- SD卡开发详细文档
- 使用html css js 书写tab切换