NIO实现服务器和客户端简单通讯与群聊系统

NIO服务端与客户端简易实现 NIO服务端与客户端简易实现 NIO简介 Non-blocking I/O 或 New I/O jdk1.4发布 1.8稳定 高并发网络服务器支持岗 编程模型 模型:对事务共性的抽象 编程模型:对编程共性的抽象 BIO网络模型缺点 阻塞式I/O模型 弹性伸缩能力差 多线程耗资源 大量并发情况下会出现多个线程等待,致使服务器压力增大,甚至使服务器崩掉 NIO网络模型猜想 Selector用于管理连接... 阅读详情

参考 https://www.bilibili.com/video/BV1DJ411m7NR

相关API汇总

public abstract class Buffer {
    //JDK1.4时,引入的api
    public final int capacity( )//返回此缓冲区的容量
    public final int position( )//返回此缓冲区的位置
    public final Buffer position (int newPositio)//设置此缓冲区的位置 public final int limit( )//返回此缓冲区的限制
    public final Buffer limit (int newLimit)//设置此缓冲区的限制 public final Buffer mark( )//在此缓冲区的位置设置标记
    public final Buffer reset( )//将此缓冲区的位置重置为以前标记的位置
    public final Buffer clear( )//清除此缓冲区, 即将各个标记恢复到初始状态,但是数据并 public final Buffer flip( )//反转此缓冲区
    public final Buffer rewind( )//重绕此缓冲区
    public final int remaining( )//返回当前位置与限制之间的元素数
    public final boolean hasRemaining( )//告知在当前位置和限制之间是否有元素
    public abstract boolean isReadOnly( );//告知此缓冲区是否为只读缓冲区


    //JDK1.6时引入的api
    public abstract boolean hasArray();//告知此缓冲区是否具有可访问的底层实现数组 public abstract Object array();//返回此缓冲区的底层实现数组
    public abstract int arrayOffset();//返回此缓冲区的底层实现数组中第一个缓冲区元素的
    public abstract boolean isDirect();//告知此缓冲区是否为直接缓冲区
}

public abstract class ByteBuffer {
    //缓冲区创建相关api
    public static ByteBuffer allocateDirect(int capacity)//创建直接缓冲区 public static ByteBuffer allocate(int capacity)//设置缓冲区的初始容量 public static ByteBuffer wrap(byte[] array)//把一个数组放到缓冲区中使用
    //构造初始化位置offset和上界length的缓冲区
    public static ByteBuffer wrap(byte[] array,int offset, int length)
    //缓存区存取相关API
    public abstract byte get( );//从当前位置position上get,get之后,position会自动+1 public abstract byte get (int index);//从绝对位置get
    public abstract ByteBuffer put (byte b);//从当前位置上添加,put之后,position会自动+1
    public abstract ByteBuffer put (int index, byte b);//从绝对位置上put
}

FileChannel //主要用来对本地文件进行 IO 操作,常见的方法有
1)	public int read(ByteBuffer dst) //从通道读取数据并放到缓冲区中
2)	public int write(ByteBuffer src) //把缓冲区的数据写到通道中
3)	public long transferFrom(ReadableByteChannel src, long position, long count)//从目标通道中复制数据到当前通道
4)	public long transferTo(long position, long count, WritableByteChannel target)//把数据从当前通道复制给目标通道


//Selector 类是一个抽象类, 常用方法和说明如下:
public abstract class Selector implements Closeable { public static Selector open();//得到一个选择器对象
    //监控所有注册的通道,当其中有IO 操作可以进行时,将对应的SelectionKey 加入到内部集合中并返回,参数用来设置超时时间
    public int select(long timeout);

    selector.select()//阻塞
    selector.select(1000);//阻塞1000毫秒,在1000毫秒后返回
    selector.selectNow();//不阻塞,立马返还
    selector.wakeup();//唤醒selector

    public Set<SelectionKey> selectedKeys();//从内部集合中得到所有的SelectionKey
}

/**
 * 1)	SelectionKey,表示 Selector 和网络通道的注册关系, 共四种:
 * int OP_ACCEPT:有新的网络连接可以 accept,值为 16
 * int OP_CONNECT:代表连接已经建立,值为 8
 * int OP_READ:代表读操作,值为 1
 * int OP_WRITE:代表写操作,值为 4
 *
 * 源码中:
 * public static final int OP_READ = 1 << 0;
 * public static final int OP_WRITE = 1 << 2;
 * public static final int OP_CONNECT = 1 << 3;
 * public static final int OP_ACCEPT = 1 << 4;
 */
public abstract class SelectionKey {
    public abstract Selector selector();//得到与之关联的Selector 对象
    public abstract SelectableChannel channel();//得到与之关联的通道
    public final Object attachment();//得到与之关联的共享数据
    public abstract SelectionKey interestOps(int ops);//设置或改变监听事件
    public final boolean isAcceptable();//是否可以 accept public final boolean isReadable();//是否可以读
    public final boolean isWritable(); // 是否可以写
}


//在服务器端监听新的客户端Socket 连接
public abstract class ServerSocketChannel extends AbstractSelectableChannel implements NetworkChannel{
    public static ServerSocketChannel open()//得到一个 ServerSocketChannel 通道
    public final ServerSocketChannel bind(SocketAddress local)//设置服务器端端口号
    public final SelectableChannel configureBlocking(boolean block)//设置阻塞或非阻塞模式,取值false 表示采用非阻塞模式
    public SocketChannel accept()//接受一个连接,返回代表这个连接的通道对象
    public final SelectionKey register(Selector sel, int ops)//注册一个选择器并设置监听事件
}

//网络 IO 通道,具体负责进行读写操作。NIO 把缓冲区的数据写入通道,或者把通道里的数据读到缓冲区。
public abstract class SocketChannel
        extends AbstractSelectableChannel
        implements ByteChannel, ScatteringByteChannel, GatheringByteChannel, NetworkChannel{
    public static SocketChannel open();//得到一个 SocketChannel 通道
    public final SelectableChannel configureBlocking(boolean block);//设置阻塞或非阻塞模式,取值false  表示采用非阻塞模式
    public boolean connect(SocketAddress remote);//连接服务器
    public boolean finishConnect();//如果上面的方法连接失败,接下来就要通过该方法完成连接操作
    public int write(ByteBuffer src);//往通道里写数据 public int read(ByteBuffer dst);//从通道里读数据
    public final SelectionKey register(Selector sel, int ops, Object att);//注册一个选择器并设置监听事件,最后一个参数可以设置共享数据
    public final void close();//关闭通道
}


server与client实现

原理概述:

  1. 当客户端连接时,会通过ServerSocketChannel 得到SocketChannel
  2. Selector 进行监听 select方法,返回有事件发生的通道的个数.
  3. 将socketChannel注册到Selector上,register(Selector sel,int ops),一个selector上可以注册多个SocketChannel
  4. 注册后返回一个Selectionkey,会和该Selector关联(集合)
  5. 进一步得到各个Selectionkey(有事件发生)
  6. 在通过SelectionKey反向获取SocketChannel,方法 channel()
  7. 可以通过得到的channel,完成业务处理
    在这里插入图片描述

NIOServer


public class NIOServer {
    public static void main(String[] args) throws Exception{

        //创建ServerSocketChannel -> ServerSocket

        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        //得到一个Selecor对象
        Selector selector = Selector.open();

        //绑定一个端口6666, 在服务器端监听
        serverSocketChannel.socket().bind(new InetSocketAddress(6666));
        //设置为非阻塞
        serverSocketChannel.configureBlocking(false);

        //把 serverSocketChannel 注册到  selector 关心 事件为 OP_ACCEPT

        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        System.out.println("注册后的selectionkey 数量=" + selector.keys().size()); // 1



        //循环等待客户端连接
        while (true) {

            //监控所有注册的通道,当其中有IO 操作可以进行时,将
            //对应的SelectionKey 加入到内部集合中并返回,参数用来设置超时时间
            //这里我们等待1秒,如果没有事件发生, 返回
            if(selector.select(1000) == 0) { //没有事件发生
                System.out.println("服务器等待了1秒,无连接");
                continue;
            }

            //如果返回的>0, 就获取到相关的 selectionKey集合
            //1.如果返回的>0, 表示已经获取到关注的事件
            //2. selector.selectedKeys() 返回关注事件的集合
            //   通过 selectionKeys 反向获取通道
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            System.out.println("selectionKeys 数量 = " + selectionKeys.size());

            //遍历 Set<SelectionKey>, 使用迭代器遍历
            Iterator<SelectionKey> keyIterator = selectionKeys.iterator();

            while (keyIterator.hasNext()) {
                //获取到SelectionKey
                SelectionKey key = keyIterator.next();
                //根据key 对应的通道发生的事件做相应处理
                if(key.isAcceptable()) { //如果是 OP_ACCEPT, 有新的客户端连接
                    //该该客户端生成一个 SocketChannel
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    System.out.println("客户端连接成功 生成了一个 socketChannel " + socketChannel.hashCode());
                    //将  SocketChannel 设置为非阻塞
                    socketChannel.configureBlocking(false);
                    //将socketChannel 注册到selector, 关注事件为 OP_READ, 同时给socketChannel关联一个Buffer
                    socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));

                    System.out.println("客户端连接后 ,注册的selectionkey 数量=" + selector.keys().size()); //2,3,4..


                }
                if(key.isReadable()) {  //发生 OP_READ

                    //通过key 反向获取到对应channel
                    SocketChannel channel = (SocketChannel)key.channel();

                    //获取到该channel关联的buffer
                    ByteBuffer buffer = (ByteBuffer)key.attachment();
                    channel.read(buffer);
                    System.out.println("form 客户端 " + new String(buffer.array()));

                }

                //手动从集合中移动当前的selectionKey, 防止重复操作
                keyIterator.remove();

            }

        }

    }
}

NIOClient

public class NIOClient {
    public static void main(String[] args) throws Exception{

        //得到一个网络通道
        SocketChannel socketChannel = SocketChannel.open();
        //设置非阻塞
        socketChannel.configureBlocking(false);
        //提供服务器端的ip 和 端口
        InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 6666);
        //连接服务器
        if (!socketChannel.connect(inetSocketAddress)) {

            while (!socketChannel.finishConnect()) {
                System.out.println("因为连接需要时间,客户端不会阻塞,可以做其它工作..");
            }
        }

        //...如果连接成功,就发送数据
        String str = "hello";
        //Wraps a byte array into a buffer
        ByteBuffer buffer = ByteBuffer.wrap(str.getBytes());
        //发送数据,将 buffer 数据写入 channel
        socketChannel.write(buffer);
        System.in.read();

    }
}

群聊系统实现

服务端:
服务端类首先会进行初始化 ,然后会进行监听,若是连接事件注册到seletor即可,并输出上线的客户端信息,若是read事件将消息打印并要转发给其它客户端。

public class GroupChatServer {
    //定义属性
    private Selector selector;
    private ServerSocketChannel listenChannel;
    private static final int PORT = 6667;

    //构造器
    //初始化工作
    public GroupChatServer() {

        try {

            //得到选择器
            selector = Selector.open();
            //ServerSocketChannel
            listenChannel =  ServerSocketChannel.open();
            //绑定端口
            listenChannel.socket().bind(new InetSocketAddress(PORT));
            //设置非阻塞模式
            listenChannel.configureBlocking(false);
            //将该listenChannel 注册到selector
            listenChannel.register(selector, SelectionKey.OP_ACCEPT);

        }catch (IOException e) {
            e.printStackTrace();
        }

    }

    //监听
    public void listen() {

        System.out.println("监听线程: " + Thread.currentThread().getName());
        try {

            //循环处理
            while (true) {

                int count = selector.select();
                if(count > 0) {//有事件处理

                    //遍历得到selectionKey 集合
                    Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                    while (iterator.hasNext()) {
                        //取出selectionkey
                        SelectionKey key = iterator.next();

                        //监听到accept
                        if(key.isAcceptable()) {
                            SocketChannel sc = listenChannel.accept();
                            sc.configureBlocking(false);
                            //将该 sc 注册到seletor
                            sc.register(selector, SelectionKey.OP_READ);

                            //提示
                            System.out.println(sc.getRemoteAddress() + " 上线 ");

                        }
                        if(key.isReadable()) { //通道发送read事件,即通道是可读的状态
                            //处理读 (专门写方法..)

                            readData(key);

                        }
                        //当前的key 删除,防止重复处理
                        iterator.remove();
                    }

                } else {
                    System.out.println("等待....");
                }
            }

        }catch (Exception e) {
            e.printStackTrace();

        }finally {
            //发生异常处理....

        }
    }

    //读取客户端消息
    private void readData(SelectionKey key) {

        //取到关联的channle
        SocketChannel channel = null;

        try {
           //得到channel
            channel = (SocketChannel) key.channel();
            //创建buffer
            ByteBuffer buffer = ByteBuffer.allocate(1024);

            int count = channel.read(buffer);
            //根据count的值做处理
            if(count > 0) {
                //把缓存区的数据转成字符串
                String msg = new String(buffer.array());
                //输出该消息
                System.out.println("form 客户端: " + msg);

                //向其它的客户端转发消息(去掉自己), 专门写一个方法来处理
                sendInfoToOtherClients(msg, channel);
            }

        }catch (IOException e) {
            try {
                System.out.println(channel.getRemoteAddress() + " 离线了..");
                //取消注册
                key.cancel();
                //关闭通道
                channel.close();
            }catch (IOException e2) {
                e2.printStackTrace();;
            }
        }
    }

    //转发消息给其它客户(通道)
    private void sendInfoToOtherClients(String msg, SocketChannel self ) throws  IOException{

        System.out.println("服务器转发消息中...");
        System.out.println("服务器转发数据给客户端线程: " + Thread.currentThread().getName());
        //遍历 所有注册到selector 上的 SocketChannel,并排除 self
        for(SelectionKey key: selector.keys()) {

            //通过 key  取出对应的 SocketChannel
            Channel targetChannel = key.channel();

            //排除自己
            if(targetChannel instanceof  SocketChannel && targetChannel != self) {

                //转型
                SocketChannel dest = (SocketChannel)targetChannel;
                //将msg 存储到buffer
                ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
                //将buffer 的数据写入 通道
                dest.write(buffer);
            }
        }

    }

    public static void main(String[] args) {
        //创建服务器对象
        GroupChatServer groupChatServer = new GroupChatServer();
        groupChatServer.listen();
    }
}

客户端


public class GroupChatClient {

    //定义相关的属性
    private final String HOST = "127.0.0.1"; // 服务器的ip
    private final int PORT = 6667; //服务器端口
    private Selector selector;
    private SocketChannel socketChannel;
    private String username;

    //构造器, 完成初始化工作
    public GroupChatClient() throws IOException {

        selector = Selector.open();
        //连接服务器
        socketChannel = socketChannel.open(new InetSocketAddress("127.0.0.1", PORT));
        //设置非阻塞
        socketChannel.configureBlocking(false);
        //将channel 注册到selector
        socketChannel.register(selector, SelectionKey.OP_READ);
        //得到username
        username = socketChannel.getLocalAddress().toString().substring(1);
        System.out.println(username + " is ok...");

    }
    //向服务器发送消息
    public void sendInfo(String info) {

        info = username + " 说:" + info;

        try {

            socketChannel.write(ByteBuffer.wrap(info.getBytes()));
        }catch (IOException e) {
            e.printStackTrace();
        }
    }
    //读取从服务器端回复的消息
    public void readInfo() {

        try {

            int readChannels = selector.select();
            if(readChannels > 0) {//有可以用的通道

                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()) {

                    SelectionKey key = iterator.next();
                    if(key.isReadable()) {
                        //得到相关的通道
                       SocketChannel sc = (SocketChannel) key.channel();
                       //得到一个Buffer
                        ByteBuffer buffer = ByteBuffer.allocate(1024);
                        //读取
                        sc.read(buffer);
                        //把读到的缓冲区的数据转成字符串
                        String msg = new String(buffer.array());
                        System.out.println(msg.trim());
                    }
                }
                iterator.remove(); //删除当前的selectionKey, 防止重复操作
            } else {
                //System.out.println("没有可以用的通道...");
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {

        //启动我们客户端
        GroupChatClient chatClient = new GroupChatClient();

        //启动一个线程, 每个3秒,读取从服务器发送数据
        new Thread() {
            public void run() {

                while (true) {
                    chatClient.readInfo();
                    try {
                        Thread.currentThread().sleep(3000);
                    }catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();

        //发送数据给服务器端
        Scanner scanner = new Scanner(System.in);

        while (scanner.hasNextLine()) {
            String s = scanner.nextLine();
            chatClient.sendInfo(s);
        }
    }
}

可启动一个服务端 两个客户端进行实验
在这里插入图片描述
GroupChatClient输入消息
在这里插入图片描述
查看服务端打印结果及是否转发
在这里插入图片描述
查看GroupChatClient(1)是否接收到 GroupChatClient发出的信息
在这里插入图片描述

AndroidGroupChatServer:使用 J2EE 的 Android 群聊服务器 悉尼推特 以下用户指南基于 Utuntu 操作系统。 安装 Ansible 要安装 ansible,请运行以下命令: $ sudo apt-get install software-properties-common $ sudo apt-add-repository ppa:ansible/ansible $ sudo apt-get update $ sudo apt-get install ansible 剧本 有 3 个 playbook 用于部署。 这些 playbook 用于在 openstack 上创建一个新实例,并安装所有必需的包和依赖项以抓取和分析推文。 播放: nova.yml使用模块 nova_compute 在 openstack 上创建一个新实例(需要提供参数 nodename 和 flavorid)。 mount.yml为要附加到实例的卷,将其格式化为 立即下载

相关推荐

应急响应靶场练习Linux-web-2

本次应急响应靶机采用的是知攻善防实验室的Linux-2应急响应靶机靶机下载地址为:相关账户密码: root/Inch@957821.(第一个为大写的i,记住要带最后的点.)1.该攻击者的IP为192.168.20.12.攻击方式应该是通过/index.php?user-app-register上传了一个webshell,然后使用蚁剑管理webshell之后再次上传version2.php进行提权.3.攻击者修改了phpmyadmin数据库的管理员密码。

tddkett的博客 2801

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

qq_41493224的博客 1331

【数据结构】平行四边形数量

平行四边形个数,哈希表,散列

cyy010617的博客 4009

Socket(NIO)实现的客户端与服务端之间通信

NIO实现的客户端与服务端之间通信

woaiwojialanxi的专栏 1718

自动驾驶仿真 (三)—— 基于PreScan与Simulink的AEB系统仿真

自动驾驶仿真三—— 基于PreScan&Simulink的AEB系统仿真1. AEB自动紧急制动系统1. 1 TTC碰撞时间模型1. 2 C-NCAP法规部分术语与定义1. 3 主动安全ADAS系统试验项目2. AEB仿真分析建模2.1 搭建场景2.2 传感器建模2.3 添加AEB控制系统3. 典型工况仿真3.1 CCRs仿真测试3.1 CCRm仿真测试4. 参考学习的书目教材 博主前面的博文已经介绍了Prescan&Simulink基本的场景建模及仿真分析流程,《自动驾驶仿真 (二)——

zhudj08的博客 1万+

FPGA SPI驱动ADC避坑指南:以ADC128S022为例,详解时序设计与代码调试

本文以ADC128S022为例,详细解析FPGA通过SPI驱动ADC的时序设计与代码调试中的常见问题。从时钟分频计算、SPI模式选择到状态机实现,提供避坑指南和实战技巧,帮助工程师解决数据采集系统中的时序匹配难题。特别针对FPGA与ADC通信中的微妙差异,给出精确的Verilog代码示例和ModelSim仿真验证方法。

weixin_42522374的博客 458

JAVA NIO实现客户端与服务端通信

使用java NIO实现nio客户端连接nio服务端发送消息 二丶NIO客户端 实现效果如下:

Dichotomy_的博客 1888

Linux系统安装部署Redis完整教程(图文详解)

最近需要在Linux服务器安装部署Redis,参考了网上很多的文章,比较零碎,所以我自己写了一篇完整的Redis安装部署文档,在部署Redis之前重装了我的华为服务器,就是为了给大家一步步阐述我的操作过程,配合图文进行讲解更加通俗易懂!

黄团团的个人博客 6692

JAVA NIO创建服务端(含代码详解)

当使用Java NIO(New I/O)创建一个服务端时,你需要使用。这里定义了一个缓冲区大小和一个超时时间,可以根据需要进行调整。配置为非阻塞模式,并绑定到指定的端口(这里使用的是8080)阻塞等待就绪的事件。如果没有任何事件就绪,将继续下一次循环。方法读取数据,并进行相应的处理。在示例中,将读取的数据存储到。这样可以确保在使用完后自动关闭它们。这是服务端的主要事件循环。事件,表示有新的客户端连接请求。集合,并遍历处理每个就绪的事件。事件,表示有数据可读取。中,并打印接收到的消息。

一叶知秋 1015

195、大模型蒸馏与压缩:知识蒸馏与VLA模型轻量化

折腾完这一整套流程,最大的感悟是:知识蒸馏不是简单的模型压缩,而是知识迁移的工程艺术。每一步都有坑,每个参数都可能影响最终性能。给后来者的建议是:先别急着上蒸馏,把teacher模型的推理延迟和显存占用测清楚,确定瓶颈在哪里——是计算量太大还是内存带宽不够,这决定了你该用蒸馏还是量化还是剪枝。蒸馏训练时一定要监控每一层的特征对齐loss,别只看总loss。如果某一层的对齐loss特别高,说明student在这一层学歪了,需要调整该层的损失权重或者增加该层的投影头容量。

sundong_81的博客 111

基于PCL、Open3d、Easy3d 、VTK等常见开源库的QT开发

PCL+QT开发

阁楼 2万+

二、NIO详解

文章目录1、缓冲区(Buffer)1.1、基本介绍1.2、Buffer类介绍1.2.1、Buffer类主要属性1.2.2、Buffer类使用示例2、通道(Channel)2.1、基本介绍2.2、FileChannel类2.2.1、常见方法2.2.2、应用实例2.3、ServerSocketChannel 和 SocketChannel 类2.3.1、常见方法2.3.2、应用实例3、Selector(选择器)3.1、基本介绍3.2、SelectionKey介绍3.3、Selector常见方法4、Demo实例4

小望没烦恼的博客 643

点云目标检测:open3d多窗口联动可视化

多个模型之间的对比除了指标之外,还需要可以直接直观的对比可视化结果,这次介绍一下如何使用open3d同时打开两个窗口分别加载两个模型的结果进行对比,同时实现两个窗口的联动,也就是当一个窗口拖动或者缩放时另外一个窗口也跟着做同样的变换。

zhaoguanhua的博客 4688

4.基于NIO的群聊系统

本文总结自B站《netty-尚硅谷》,很不错;

PacosonSWJTU的博客 641

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Java NIO 应用案例:实现一个简单的群聊系统

本文基于NIO实现了一个简单的群聊系统来巩固NIO所学的知识。该案例实现了服务器端和客户端之间的数据简单通讯。 服务器端功能:监测用户上线,离线;实现客户端消息的转发功能(将该客户端的消息转发给其它客户端)。 客户端功能:通过 channel 无阻塞地发送消息给其它所有用户,同时可以接受其它用户发送的消息(由服务器转发得到)。

正在努力工作的搬砖人 2471

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

使用nio编写一个简单群聊系统,实现服务器端和客户端的数据通信

使用NIO技术编写一个简单的群聊技术来了解ServerSocketChannel,SocketChannel,Selector,SelectionKey等技术的使用技巧与方法。 服务器端的代码: 服务器端代码 package com.yu.nio; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.*; import java.util.Iterator; impo

煜城的博客 628

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

NIO系列:5.NIO群聊系统

前面的文章介绍了NIO的三大核心组件并编写了BIO的一个demo实例,本文使用NIO写一个小应用实例,巩固并加深对NIO的理解。 实例要求: 1)编写一个 NIO 群聊系统,实现服务器端和客户端之间的数据简单通讯(非阻塞) 2)实现多人群聊 3)服务器端:可以监测用户上线,离线,并实现消息转发功能 4)客户端:通过channel 可以无阻塞发送消息给其它所有用户,同时可以接受其它用户发送的消息(有...

天高任鸟飞,海阔凭鱼跃 3672

用NIO实现在线群聊

用Java里NIO的原生API搭建一个在线群聊系统。编写一个NIO群聊系统,实现服务器端和客户端之间的数据简单通讯(非阻塞)能够实现多人群聊(多客户端)服务器端:可以监测用户上线,离线,并实现消息转发功能客户端:通过Channel可以无阻塞发送消息给其它所有用户,同时可以接受其它用户发送的消息(由服务器转发得到)serverSocketChannel是否有,有就会在中把serverSocketChannel的下来)socketChannel是否有,有就会在中把socketChannel的下来)触发。

m0_72397750的博客 967

基于NIO的群聊系统简单实现

实例要求: (1)编写一个NIO多人群聊系统,实现服务器端和客户端之间的数据简单通讯(非阻塞) (2)服务器端:可以监测用户上线、离线,并实现消息转发功能 (3)客户端:通过channel可以无阻塞发送消息给其它所有用户,同时可以接受其它用户发送的消息(都是由服务器转发得到) (4)目的:进一步理解NIO非阻塞网络编程机制 服务器 package nio.groupchat; import ...

以后我要当村长 265

Netty剖析之NIO群聊系统

前言 在前面我们详细讲解了BIO、NIO,本次我们将使用NIO来完成一个群聊系统,实现服务器端和客户端之间的数据简单通讯(非阻塞); 群聊系统基本要求: 服务器端可监测客户端上线、离线、并转发客户端消息; 客户端可群发消息给其它用户,也可接收其它客户发送的消息; 代码示例 服务端: public class GroupChatServer { private Selector sel...

皓晨的架构笔记 329

手把手教你实现NIO群聊系统

前面我们一起学习了NIO的基础知识,下面将用我们学习到的知识实现一个简单的群聊系统。 需求: 编写一个 NIO 群聊系统,实现服务器端和客户端之间的数据简单通讯(非阻塞) 实现多人群聊 服务器端:可以监测用户上线,离线,并实现消息转发功能 客户端:通过 channel 可以无阻塞发送消息给其它所有用户,同时可以接受其它用户发送的消息(有服务器转发 得到) 示意图分析: 详细设计如下: 先编写服务器端 1.1. 服务器启动并监听 6667 1.2 服务器接收客户端信息,并实现转发 [处.

JeremyIverson的博客 553

Java NIO网络编程之群聊系统

概述 对ServerSocketChannel、SocketChannel、SelectionKey有一定的理解和了解对应API。 NIO非阻塞网络编程相关关系梳理: 以下概念: ServerSocketChannel:可以类比BIO网络编程的ServerSocket,属于服务端的Socket,用于监听接收客户端连接。 SocketChannel:类比Socket,用于连接两台计算机的套接字,只是支持非阻塞。 Selector:多路复用器。 SelectionKey:与Channel进行绑定,Select

qq_40837310的博客 373

Java NIO之群聊系统

概述 对ServerSocketChannel、SocketChannel、SelectionKey有一定的理解和了解对应API。 NIO非阻塞网络编程相关关系梳理: 以下概念: ServerSocketChannel:可以类比BIO网络编程的ServerSocket,属于服务端的Socket,用于监听接收客户端连接。 SocketChannel:类比Socket,用于连接两台计算机的套接字,只是支持非阻塞。 Selector:多路复用器。 SelectionKey:与Channel进行绑定,Selec

lixinkuan的博客 471

NIO 网络编程之群聊系统

NIO -- 群聊系统 基本要求 群聊系统实现服务器端和客户端之间的数据简单通讯(非阻塞)。 实现多人群聊 服务器端:可以监测用户上线、下线、、并实现消息转发。 客户端:可无阻塞发送消息给其他所有用户,同时可以接受其他用户消息(由服务器转发得到)。 实现思路 先编写服务器,服务器启动监听、 服务器可接受客户端信息进行转发 再编写客户端,连接服务器、发送消息、接受消息 具体代码 服...

baidu_41922630的博客 387

Java BIO、NIO(通信/群聊系统、零拷贝)、AIO

BIO适用于连接数较少的场景,NIO适用于中等并发场景,而AIO适用于高并发的异步操作场景,如网络服务器、文件传输等。选择适当的I/O模型取决于应用程序的性能和并发需求。

日常记录 1142
上一篇: 坑,使用Powershell运行Jar包出错:找不到或无法加载主类
下一篇: SpeedMent入门&集成SpringBoot&Stream常见操作
金心靖晨
博客等级 码龄9年 460粉丝 211原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值