• NIO-Socket实现简易聊天室


    NIO实现通信聊天:

    服务端步骤:

    1.创建NI0通道,并且绑定端口

    2.开启非阻塞模式

    3.创建Selector选择器,并将通道注册到选择器上边,设置关系事件---》新链接

    4.循环监听通道的事件

    5.监听到新连接事件

    5.1:建立和客户端连接的通道

    5.2:通道设置为非阻塞

    5.3:通道设置完成,将关系事件设置为读取

    6.监听到读取事件

    6.1:获取客户端通道

    6.2:将通道的数据写入到缓冲区(buffer)当中

    6.3:打印数据

    服务器端:

    1. public class Server {
    2. public static void main(String[] args) throws IOException {
    3. // 获取一个ServerSocket通道
    4. ServerSocketChannel serverChannel = ServerSocketChannel.open();
    5. // serverChannel通道一直监听4700端口
    6. serverChannel.socket().bind(new InetSocketAddress(4700));
    7. // 设置serverChannel为非阻塞
    8. serverChannel.configureBlocking(false);
    9. //创建Selector选择器用来监听通道
    10. Selector selector = Selector.open();
    11. // 把ServerSocketChannel注册到selector中,并且selector对客户端的连接操作感兴趣
    12. serverChannel.register(selector, SelectionKey.OP_ACCEPT);
    13. System.out.println("服务启动成功!");
    14. while (true) {
    15. /*
    16. * 如果事件没有到达 selector.select() 会一直阻塞等待
    17. */
    18. selector.select();
    19. Set selectionKeys = selector.selectedKeys();
    20. Iterator iterator = selectionKeys.iterator();
    21. while (iterator.hasNext()) {
    22. SelectionKey key = iterator.next();
    23. if (key.isAcceptable()) // 如果是OP_ACCEPT事件,则进行连接获取和事件注册
    24. {
    25. ServerSocketChannel server = (ServerSocketChannel) key.channel(); //连接获取
    26. SocketChannel socketChannel = server.accept(); // 获取通道
    27. socketChannel.configureBlocking(false); // 设置为非阻塞
    28. socketChannel.register(selector, SelectionKey.OP_READ); //这里只注册了读事件,如果需要给客户端写数据,则需要注册写事件
    29. System.out.println("客户端连接成功!");
    30. } else if (key.isReadable()) //如果是OP_READ事件,则进行读取和打印
    31. {
    32. SocketChannel socketChannel = (SocketChannel) key.channel();
    33. ByteBuffer byteBuffer = ByteBuffer.allocate(128);//创建Buffer
    34. int len = socketChannel.read(byteBuffer);
    35. if (len > 0) //如果有数据,则打印数据
    36. {
    37. System.out.println("接受到客户端数据" + new String(byteBuffer.array()));
    38. }
    39. }
    40. // 从事件集合中删除本次处理的key,防止下次select重复处理
    41. iterator.remove();
    42. }
    43. }
    44. }
    45. }

    客户端:

    1. public class Client {
    2. public static void main(String[] args) throws IOException {
    3. //打开channel通道
    4. SocketChannel socketChannel = SocketChannel.open();
    5. socketChannel.configureBlocking(false); //设置为非阻塞
    6. InetSocketAddress address = new InetSocketAddress("101.43.152.120",4700);
    7. while (!socketChannel.connect(address)){
    8. while (!socketChannel.finishConnect()){
    9. System.out.println("连接中,客户端可以进行其他工作");
    10. }
    11. // Scanner scanner = new Scanner(System.in);
    12. // String str = scanner.next();
    13. Scanner scanner=new Scanner(System.in);
    14. do {
    15. String str=scanner.next();
    16. ByteBuffer aa = ByteBuffer.wrap(str.getBytes()); // 将数据转换成字节信息写入到Buffer当中
    17. socketChannel.write(aa); //将Buffer当中的数据写入channel
    18. } while (!scanner.equals("bye"));
    19. scanner.close();
    20. System.in.read();
    21. }
    22. }
    23. }

  • 相关阅读:
    coding上的免费的编译、打包、推镜像工具(cicd)太强了,必须分享一下
    java-php-net-python-东软健身会员网站计算机毕业设计程序
    Linux中线程的介绍
    oracle 12c GI卸载流程
    【C语言】深度剖析数据在内存中的存储
    通信相关常识
    12.springboot中使用自定义Filter
    链表的分割——哨兵位
    Android 12.0 SystemUI状态栏屏蔽掉通知栏不显示通知
    SQL注入实例(sqli-labs/less-9)
  • 原文地址:https://blog.csdn.net/weixin_47796247/article/details/127891040