尚硅谷2019年Netty教程 NIO 群聊系统 ----目标netty---step4.01

  • 尚硅谷2019年Netty教程 netty 群聊系统 ----目标netty—step5.02
    *https://blog.csdn.net/wei198621/article/details/108764920

  • 需要与 下面的进行对比学习,就可以知道 netty的好了

  • 尚硅谷2019年Netty教程 NIO 群聊系统 ----目标netty—step4.01

  • https://blog.csdn.net/wei198621/article/details/108700129

https://www.bilibili.com/video/BV1jK4y1s7GV?p=29
https://www.bilibili.com/video/BV1jK4y1s7GV?p=30
https://www.bilibili.com/video/BV1jK4y1s7GV?p=31
https://www.bilibili.com/video/BV1jK4y1s7GV?p=32
尚硅谷2019年Netty教程 NIO 群聊系统 一共分为4讲
29,30 ----server端编码
31,32 ----client编码
32 的后半部分是对 之前代码的修改,主要有两点
part1 服务端 GroupChartServer
// 别忘将客户端 置为 非阻塞
public void listen(){
if(key.isAcceptable()){
sc.configureBlocking(false) ; //设置客户端非阻塞
}

part2 客户端 GroupChatClient

//读取从服务器 回复的消息   别忘删除  SelectionKey
public void readInfo(){
                iterator.remove();  //读取后,别忘了删除当前 selectionKey
 }

服务端 代码


package com.atguigu.groupChat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Channel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/**
 * Author: tz_wl
 * Date: 2020/9/20 21:41
 * Content:
 *
 * 1.1  服务器启动并监听 * 端口
 1.2  打印上线信息
 1.2  打印数据信息
 1.3  打印转发消息
 1.4  打印离线消息
 *
 *
 */
public class GroupChartServer {

    //01 定义 需要都用到的变量
    private Selector selector ;
    private ServerSocketChannel listenChannel;
    private static final int PORT = 8095;

    //02  构造函数 初始化    注册 serverSocketChannel 到 Selector
    public GroupChartServer() throws  Exception{
        try {
            selector = Selector.open();
            listenChannel = ServerSocketChannel.open();
            listenChannel.socket().bind(new InetSocketAddress(PORT));
            listenChannel.configureBlocking(false);
            listenChannel.register(selector , SelectionKey.OP_ACCEPT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }



    // 03  服务端 监听函数
    //      isAcceptable     有客户端连接上来 打印 ***客户端连接到服务器了
    //      isReadable       客户端发送的数据 放到单独方法  readData  中处理
    public void listen(){
        try{
            System.out.println("服务端已经启动 ...  ");
            while(true){
                int count= selector.select(2000);
                if(count>0){
                    Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                    while(iterator.hasNext()){
                        SelectionKey key= iterator.next();
                        if(key.isAcceptable()){
                            SocketChannel sc = listenChannel.accept();
                            sc.configureBlocking(false) ;            //设置客户端非阻塞
                            sc.register(selector,SelectionKey.OP_READ);
                            //提示 某某客户端  上线了
                            System.out.println(sc.getRemoteAddress()+"上线");
                        }
                        if(key.isReadable()){
                            // 专门方法处理读事件
                            readData(key);
                        }
                        iterator.remove();// 注意要删除 别忘记
                    }
                }else{
                    //System.out.println("waiting ...");
                }
            }
        }catch(IOException e){
            e.printStackTrace();
        }finally{
        }
    }

    //读取客户端消息
    // 读到数据了  提示 有客户端发来消息
    // 其他客户端转发 消息
    // 有客户端离线了,提示  离线了
    private void readData(SelectionKey key){
        SocketChannel channel = null;
        try{
            channel= (SocketChannel) key.channel();
            ByteBuffer buffer=ByteBuffer.allocate(1024);
            int count = channel.read(buffer);
            if(count>0){
                String msg = new String(buffer.array());
                System.out.println("from 客户端  msg is:" + msg );
                //  向 其他客户端转发消息  专用方法
                sendInfoToOtherClients(msg,channel);
            }

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

            }
        }
    }


    //转发消息给其他客户
    private void sendInfoToOtherClients(String msg, SocketChannel self) throws IOException {
        System.out.println("服务器转发消息中... ");
        //遍历 所有 注册到 selector 上面的socketChannel -  self
        for(SelectionKey key: selector.keys()){
            Channel targetChannel = key.channel();
            //如果就一个服务器  只要  targetChannel != self 就可以
            //考虑到多台服务器 if(targetChannel instanceof SocketChannel )
            if(targetChannel instanceof SocketChannel && targetChannel != self)
            {
                SocketChannel dest = (SocketChannel) targetChannel;
                ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
                dest.write(buffer);
            }
        }
    }

    public static void main(String[] args) throws Exception {
        GroupChartServer groupChatServer =  new  GroupChartServer();
        groupChatServer.listen();
    }

}

客户端代码

package com.atguigu.groupChat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;

/**
 * Author: tz_wl
 * Date: 2020/9/20 21:41
 * Content:
 *
 * //客户端
 //链接服务器
 //接收消息
 //发送消息
 */
public class GroupChatClient {

    //定义 用到的变量
    private final String HOST = "127.0.0.1";
    private final int PORT = 8095;
    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);
        socketChannel.register(selector, SelectionKey.OP_READ);
        userName = socketChannel.getLocalAddress().toString().substring(1);
        System.out.println(userName+ "  is Starting  ...");
    }


    //向服务器发送消息
    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();
                    //此处client只有 readable 没有 acceptable
                    if(key.isReadable()){
                        SocketChannel sc = (SocketChannel)key.channel();
                        ByteBuffer buffer =ByteBuffer.allocate(1034);
                        sc.read(buffer);
                        //
                        String msg = new String (buffer.array());
                        System.out.println(msg);
                    }

                    iterator.remove();  //读取后,别忘了删除当前 selectionKey
                }
            }else{
                System.out.println("没有可用通道");
            }
        }catch(Exception e){
        }
    }

    //  本线程   监听 System.in  nextLine  发送数据给服务端
    //    // //启动一个线程  每隔 3 秒 ,读取从服务器发送的数据
    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);
        }
    }
}


版权声明:本文为wei198621原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。