IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> Java NIO实现服务端与客户端 -> 正文阅读

[开发测试]Java NIO实现服务端与客户端

  • 服务端启动类
public class TimeServer {
    public static void main(String[] args) {
        int port=8080;
        MultiplexerTimeServer timeServer = new MultiplexerTimeServer(port);
        new Thread(timeServer,"NIO-MultiplexerTimeServer-001").start();
    }
}

服务端实现代码

package Nio;

import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

public class MultiplexerTimeServer implements Runnable {
    private Selector selector;
    private ServerSocketChannel serverSocketChannel;
    private volatile boolean stop;

    public MultiplexerTimeServer(int port) {
        try {
//            创建多路复用器
            selector = Selector.open();
//            用户监听所有客户端的连接,他是所有客户端连接的父管道
            serverSocketChannel = ServerSocketChannel.open();
//            设置连接为非堵塞模式
            serverSocketChannel.configureBlocking(false);
//            绑定监听端口
            serverSocketChannel.socket().bind(new InetSocketAddress(port), 1024);
//            将serverSocketChannel注册到selector线程的多路复用器用来监听accept事件
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            System.out.println("The time server is start in port :" + port);
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    public void stop() {
        this.stop = true;
    }

    //    启动多路复用器线程
    @Override
    public void run() {
//        轮询准备就绪的key
        while (!stop) {
            try {
                selector.select(1000);
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                SelectionKey selectionKey = null;
                while (iterator.hasNext()) {
                    selectionKey = iterator.next();
                    iterator.remove();
                    try {
                        handleInput(selectionKey);
                    } catch (Exception e) {
                        if (selectionKey != null) {
                            selectionKey.cancel();
                            if (selectionKey.channel() != null) {
                                selectionKey.channel().close();
                            }
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (selector != null) {
            try {
                selector.close();
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }

    private void handleInput(SelectionKey selectionKey) throws IOException {
        if (selectionKey.isValid()) {
//            连接信号
            if (selectionKey.isAcceptable()) {
//                通过key拿到父管道
                ServerSocketChannel channel = (ServerSocketChannel) selectionKey.channel();
//                多路复用器监听到有新的客户端接入,处理新的接入请求,完成tcp三次握手,建立物理链路
                SocketChannel accept = channel.accept();
//                设置为非堵塞模式
                accept.configureBlocking(false);
//                把客户端通道注册到多路复用器上,用来监听接收消息事件,此刻才有接收信息的事件功能
                accept.register(selector, SelectionKey.OP_READ);
            }
//            收到消息信号
            if (selectionKey.isReadable()) {
                SocketChannel channel = (SocketChannel) selectionKey.channel();
//                分配一个1024容量的空间
                ByteBuffer allocate = ByteBuffer.allocate(1024);
                int read = channel.read(allocate);
                if (read > 0) {
                    allocate.flip();
                    byte[] bytes = new byte[allocate.remaining()];
                    allocate.get(bytes);
                    for (byte b :
                            bytes) {
                        System.out.print(Integer.toHexString(b));
                    }
                    System.out.println();
                    String body = new String(bytes, "UTF-8");
                    System.out.println("order:" + body);
                    String currentTime = body.contains("ORDER") ? new java.util.Date(System.currentTimeMillis()).toString() : "BAD ORDER";
                    doWrite(channel, currentTime);
                } else if (read < 0) {
                    selectionKey.cancel();
                    channel.close();
                } else {

                }
            }
        }
    }

    private void doWrite(SocketChannel channel, String currentTime) throws IOException {
        if (currentTime != null && currentTime.trim().length() > 0) {
            byte[] bytes = currentTime.getBytes();
            ByteBuffer write = ByteBuffer.allocate(bytes.length);
            write.put(bytes);
            write.flip();
            channel.write(write);
        }
    }
}

客户端启动类,此处把发送独立成一个方法可以主动发送

public class Client {
    public static void main(String[] args) throws Exception {
        int port = 15001;
        TimeClientHandle_Demo timeClientHandle = new TimeClientHandle_Demo("127.0.0.1", port, 10000);
        new Thread(timeClientHandle, "Time_client").start();
        Thread.sleep(5000);
        Map<SocketChannel, Integer> map = timeClientHandle.getMap();
        Set<Map.Entry<SocketChannel, Integer>> entries = map.entrySet();
        for (int i = 0; i < 10; i++) {
            long start=System.currentTimeMillis();
            Iterator<Map.Entry<SocketChannel, Integer>> iterator = entries.iterator();
            while (iterator.hasNext()) {
                Map.Entry<SocketChannel, Integer> next = iterator.next();
                SocketChannel key = next.getKey();
                if (i == 0) {
                    timeClientHandle.doWrite(key, ProtoModel.Online(UUID.randomUUID().toString()));
                }else {
                    timeClientHandle.doWrite(key, "000000028E8F");
                }
            }
            System.out.println(System.currentTimeMillis()-start);
            Thread.sleep(30000);
        }
        timeClientHandle.setStop(true);

    }
}

客户端实现

class TimeClientHandle_Demo implements Runnable {

    private String host;
    private int port;
    private Selector selector;

    public void setStop(boolean stop) {
        this.stop = stop;
    }

    private volatile boolean stop;
    private ArrayList<SocketChannel> arrayList = new ArrayList<>();

    public Map<SocketChannel, Integer> getMap() {
        return map;
    }

    private Map<SocketChannel, Integer> map = new HashMap<>();


    public static byte[] hexStrToBinaryStr(String hexString) {
        if (hexString.isEmpty()) {
            return null;
        }
        hexString = hexString.replaceAll(" ", "");
        int len = hexString.length();
        int index = 0;
        byte[] bytes = new byte[len / 2];
        while (index < len) {
            String sub = hexString.substring(index, index + 2);
            bytes[index / 2] = (byte) Integer.parseInt(sub, 16);
            index += 2;
        }
        return bytes;
    }

    public TimeClientHandle_Demo(String ipadress, int port, int count) {
        this.host = ipadress == null ? "127.0.0.1" : ipadress;
        this.port = port;
        try {
            selector = Selector.open();
            while (count-- > 0) {
                arrayList.add(SocketChannel.open());
            }
            try {
                doConnect();
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(1);
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    @Override
    public void run() {
        while (!stop) {
            try {
                selector.select(100);
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                SelectionKey key = null;
                while (iterator.hasNext()) {
                    key = iterator.next();
                    iterator.remove();
                    try {
                        handleInput(key);
                    } catch (Exception e) {
                        if (key != null) {
                            key.cancel();
                            if (key.channel() != null) {
                                key.channel().close();
                            }
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
                System.exit(1);
            }
        }
        if (selector != null) {
            try {
                selector.close();
                Iterator<SocketChannel> iterator = arrayList.iterator();
                while (iterator.hasNext()) {
                    SocketChannel next = iterator.next();
                    next.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void doConnect() throws Exception {
        Iterator<SocketChannel> iterator = arrayList.iterator();
        while (iterator.hasNext()) {
            SocketChannel socketChannel = iterator.next();
            socketChannel.configureBlocking(false);
            if (socketChannel.connect(new InetSocketAddress(host, port))) {
                socketChannel.register(selector, SelectionKey.OP_READ);
            } else {
                socketChannel.register(selector, SelectionKey.OP_CONNECT);
            }
        }
    }

    public void doWrite(SocketChannel socketChannel, String msg) throws Exception {
//        byte[] bytes = msg.getBytes();
        byte[] bytes = hexStrToBinaryStr(msg);
        ByteBuffer allocate = ByteBuffer.allocate(bytes.length);
        allocate.put(bytes);
        allocate.flip();
        socketChannel.write(allocate);
    }

    private void handleInput(SelectionKey selectionKey) throws Exception {
        if (selectionKey.isValid()) {
            SocketChannel sc = (SocketChannel) selectionKey.channel();
            if (selectionKey.isConnectable()) {
                if (sc.finishConnect()) {
                    sc.register(selector, SelectionKey.OP_READ);
//                    doWrite(sc, "000000028E8F");
                } else {
                    map.remove(sc);
                    System.exit(1);
                }
                if (!map.containsKey(sc)) {
                    map.put(sc, sc.socket().getLocalPort());
                }
            }
            if (selectionKey.isReadable()) {
                if (!map.containsKey(sc)) {
                    map.put(sc, sc.socket().getLocalPort());
                }
                ByteBuffer allocate = ByteBuffer.allocate(1024);
                int read = sc.read(allocate);
                if (read > 0) {
                    allocate.flip();
                    byte[] bytes = new byte[allocate.remaining()];
                    allocate.get(bytes);
                    String body = new String(bytes, "UTF-8");
//                    System.out.println("收到" + body);
                } else if (read < 0) {
                    selectionKey.cancel();
                    sc.close();
                } else {

                }
            }
        }

    }
}
  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2022-03-30 18:55:28  更:2022-03-30 18:57:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/18 0:13:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码