国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Netty簡易聊天室

這篇具有很好參考價值的文章主要介紹了Netty簡易聊天室。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

本文目的

  • 通過一個簡易的聊天室案例,講述Netty的基本使用。同時分享案例代碼。
  • 項目中用到了log4j2,junit5,同時分享這些基礎(chǔ)組件的使用。
  • 項目中用到了awt,屬于古董技術(shù),只是用來做界面。非重點不用關(guān)注。

環(huán)境說明

開發(fā)工具:idea2023,jdk:1.8,Maven:3.6.3

maven依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.xxx</groupId>
    <artifactId>xxx</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>xxx</name>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.21</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.28</version>
        </dependency>

        <!-- log4j2-slf4j-適配器 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.20.0</version>
        </dependency>

        <!-- log4j2 日志核心 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.20.0</version>
        </dependency>

        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.96.Final</version>
        </dependency>

        <!-- 單元測試,Junit5 -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.9.3</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

日志配置

src/main/resources/log4j2.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!-- log4j2配置文件 -->
<!-- monitorInterval="30" 自動加載配置文件的間隔時間,不低于10秒;生產(chǎn)環(huán)境中修改配置文件,是熱更新,無需重啟應(yīng)用
 status="info" 日志框架本身的輸出日志級別,可以修改為info, -->
<Configuration status="warn" monitorInterval="30">
    <!-- 集中配置屬性,使用時通過:${LOG_HOME} -->
    <properties>
        <!-- 當(dāng)前項目名稱,供下方引用 -->
        <property name="PROJECT_NAME" value="tank-battle"/>
        <!-- 默認(rèn)日志格式-包名自動縮減(同步異步通用) -->
        <property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS}|%-5level|%-5t|%logger{1.}: %msg%n"/>
        <!-- 日志格式-打印代碼的精確位置信息,類,方法,行。(建議同步使用)。異步如果打印位置信息,會有嚴(yán)重性能問題 -->
        <property name="LOG_PATTERN_ALL" value="%d{yyyy-MM-dd HH:mm:ss.SSS}|%-5level|%-5t|%location: %msg%n"/>
        <!-- 日志主目錄。如果想把日志輸出到tomcat底下時使用。 -->
        <property name="LOG_HOME">${web:rootDir}/WEB-INF/logs</property>
    </properties>

    <!-- 日志打印輸出方式 -->
    <Appenders>
        <Console name="STDOUT" target="SYSTEM_OUT">
            <PatternLayout charset="UTF-8" Pattern="${LOG_PATTERN}"/>
        </Console>

        <RollingFile name="FileLog" fileName="logs/${PROJECT_NAME}.log" filePattern="logs/${PROJECT_NAME}-%d_%i.log">
            <PatternLayout charset="UTF-8" Pattern="${LOG_PATTERN}"/>
            <Policies>
                <!-- 每天生成一個,同時如果超過10MB還會再生成 -->
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="50 MB"/>
            </Policies>
            <DefaultRolloverStrategy max="99"/>
        </RollingFile>
    </Appenders>

    <!-- 將代碼路徑與上面的日志打印關(guān)聯(lián)起來 -->
    <Loggers>
        <!-- 當(dāng)前項目日志 -->
        <Logger name="com.sjj" level="INFO" additivity="false">
            <AppenderRef ref="STDOUT"/>
            <AppenderRef ref="FileLog"/>
        </Logger>

        <!-- 第三方依賴項目日志 -->
        <logger name="org.springframework" level="info"/>
        <logger name="org.jboss.netty" level="warn"/>

        <!--日志級別以及優(yōu)先級排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
        <!-- 根節(jié)點日志,除了上面配置的之外的日志 -->
        <Root level="WARN">
            <AppenderRef ref="STDOUT"/>
            <AppenderRef ref="FileLog"/>
        </Root>
    </Loggers>
</Configuration>

單元測試

確認(rèn)項目已加入Junit5依賴,就是如下這段。

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.9.3</version>
            <scope>test</scope>
        </dependency>

新建單元測試類的步驟。

  1. 在要創(chuàng)建單元測試的功能類上,依次點Code > generate > Test
  2. 然后在彈出的窗口中,選擇Junit版本為5,測試類名,測試方法等。然后點確定。
  3. Netty簡易聊天室,Java,Netty,java
  4. IDEA會自動根據(jù)功能類的路徑在test目錄中創(chuàng)建相同路徑但以Test結(jié)尾的測試類。并且會自動生成勾選方法的默認(rèn)測試代碼。
  5. 根據(jù)程序的輸入和輸出,編寫單元測試代碼。
  6. 點擊方法左邊的綠色三角形就可以執(zhí)行單元測試用例了。

為什么要進(jìn)行單元測試?

  1. 方法內(nèi)部可以很復(fù)雜,如果靠肉眼觀察,比較耗時間。單元測試可以根據(jù)入?yún)⒑头祷刂禍y試方法是否達(dá)到要求。
  2. 代碼是開發(fā)人員寫的,最了解代碼邏輯的還是開發(fā)人員。測試人員測試不到代碼細(xì)節(jié)。
  3. 在一個大的功能中,可能會有很多方法,每個方法都要寫Main方法來一個個測試比較復(fù)雜,而且也不知道測了哪些場景。

為什么有的公司不做單元測試。

  1. 代碼業(yè)務(wù)可能比較簡單,程序員讀代碼不是很費(fèi)力。
  2. 寫單元測試需要額外花時間,程序員工作比較忙,沒時間寫。

功能介紹

簡易版聊天室程序。主要用于練習(xí)Netty的使用。聊天室功能如下:

  1. 聊天室支持多客戶端,每個客戶端都可以看到其他客戶端的消息。
  2. 點擊關(guān)閉按鈕時,關(guān)閉當(dāng)前客戶端,同時在服務(wù)端的客戶端列表中也刪除。
  3. 系統(tǒng)UI非重點,一切從簡。

開發(fā)步驟

  1. 首先寫一個聊天室的界面(ChatFrame.java)

    1. 參考坦克大戰(zhàn)的界面部分,設(shè)置好聊天室的長寬和坐標(biāo)。

    2. 界面包含2個輸入部分,中間文本域顯示當(dāng)前聊天室的所有聊天內(nèi)容。底部文本框輸入當(dāng)前用戶的聊天內(nèi)容

    3. 聊天室窗口初始化時,需要與服務(wù)端建立連接。

    4. 當(dāng)用戶輸入完聊天內(nèi)容后回車,需要將聊天內(nèi)容通過Netty客戶端發(fā)送給服務(wù)端。

    5. 當(dāng)用戶關(guān)閉窗口時,關(guān)閉當(dāng)前客戶端,同時在服務(wù)端的客戶端列表中也刪除。

    6. /**
       * 聊天室客戶端-界面<br>
       *
       * @author namelessmyth
       * @version 1.0
       * @date 2023/8/15
       */
      @Slf4j
      public class ChatFrame extends Frame {
          public static final int GAME_WIDTH = ConfigUtil.getInt("chat.frame.width");
          public static final int GAME_HEIGHT = ConfigUtil.getInt("chat.frame.height");
          TextArea ta = new TextArea();
          TextField tf = new TextField();
      
          public static final ChatFrame INSTANCE = new ChatFrame();
      
          public static void main(String[] args) throws Exception {
              INSTANCE.setVisible(true);
              ChatClient.connect();
          }
      
          private ChatFrame() throws HeadlessException {
              //創(chuàng)建游戲的主Frame
              this.setTitle("chat room");
              this.setSize(GAME_WIDTH, GAME_HEIGHT);
              this.setLocation(800, 100);
              this.add(ta, BorderLayout.CENTER);
              this.add(tf, BorderLayout.SOUTH);
      
              tf.addActionListener(new ActionListener() {
                  @Override
                  public void actionPerformed(ActionEvent e) {
                      ChatClient.send(tf.getText());
                      tf.setText("");
                  }
              });
      
              this.addWindowListener(new WindowAdapter() {
                  @Override
                  public void windowClosing(WindowEvent e) {
                      ChatClient.close();
                      System.exit(0);
                  }
              });
              log.info("chat room Main frame initialization completed");
          }
      
          public void updateText(String text) {
              ta.setText(ta.getText() + Constants.LINE_SEPERATOR + text);
          }
      }
      
  2. 編寫Netty客戶端與服務(wù)端進(jìn)行消息通信(ChatClient.java)。

    1. 參考上面的描述,客戶端需要實現(xiàn)如下方法。

      1. connect(),與服務(wù)端建立連接的方法
      2. send(),向服務(wù)端發(fā)送聊天消息的方法。
      3. channelRead,讀取服務(wù)端信息更新客戶端聊天內(nèi)容方法
      4. 參考代碼如下
    2. @Slf4j
      public class ChatClient {
          private static SocketChannel channel;
      
          /**
           * 與服務(wù)端建立連接的方法
           */
          public static void connect() {
              EventLoopGroup group = new NioEventLoopGroup(1);
              try {
                  Bootstrap b = new Bootstrap();
                  b.group(group);
                  b.channel(NioSocketChannel.class);
                  b.handler(new ChannelInitializer<SocketChannel>() {
                      @Override
                      protected void initChannel(SocketChannel ch) throws Exception {
                          channel = ch;
                          ch.pipeline().addLast(new MyClientHandler());
                      }
                  });
                  ChannelFuture cf = b.connect("localhost", 8888).sync();
                  //直到服務(wù)器被關(guān)閉,否則一直阻塞。
                  cf.channel().closeFuture().sync();
                  log.info("the chat client has been closed.");
              } catch (Exception e) {
                  log.error("ChatClient.connect.Exception.", e);
              } finally {
                  group.shutdownGracefully();
              }
          }
      
          /**
           * 向服務(wù)端發(fā)送聊天消息的方法
           * @param msg 聊天內(nèi)容
           */
          public static void send(String msg) {
              channel.writeAndFlush(Unpooled.copiedBuffer(msg.getBytes()));
              log.info("client.send().{}", msg);
          }
      
          /**
           * 關(guān)閉客戶端方法,向服務(wù)端發(fā)送特定消息告知其刪除本客戶端。
           */
          public static void close() {
              send("__88__");
              channel.close();
          }
      }
      
      @Slf4j
      class MyClientHandler extends ChannelInboundHandlerAdapter {
          /**
           * 讀取服務(wù)端數(shù)據(jù)
           * @param msg 服務(wù)端數(shù)據(jù)
           */
          @Override
          public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
              ByteBuf buf = (ByteBuf) msg;
              String text = buf.toString(StandardCharsets.UTF_8);
              ChatFrame.INSTANCE.updateText(text);
              log.info("channelRead.msg:{}", text);
          }
      
          /**
           * 連接剛建立時的事件處理
           */
          @Override
          public void channelActive(ChannelHandlerContext ctx) throws Exception {
              log.info("connected to server.");
          }
      
          /**
           * 異常處理
           */
          @Override
          public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
              log.error("chat client exceptionCaught:", cause);
              super.exceptionCaught(ctx, cause);
          }
      }
      
  3. 聊天室服務(wù)端(ChatServer.java)。

    1. 服務(wù)端需要記錄所有的客戶端。(可能有多個)

    2. 當(dāng)某個客戶端發(fā)來消息之后,需要將消息轉(zhuǎn)發(fā)給所有客戶端。

    3. 當(dāng)接收到特殊消息時(客戶端關(guān)閉),需要將客戶端從列表中移除。

    4. @Slf4j
      public class ChatServer {
          static ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
      
          public static void main(String[] args) throws Exception {
              //總管線程組
              EventLoopGroup bossGroup = new NioEventLoopGroup(1);
              //接待員線程
              EventLoopGroup workerGroup = new NioEventLoopGroup(2);
              //服務(wù)器啟動輔助類
              ServerBootstrap b = new ServerBootstrap();
              //放在第一位的是總管線程組,第二位的就是接待員線程組。
              b.group(bossGroup, workerGroup);
              //異步全雙工
              b.channel(NioServerSocketChannel.class);
              //接收到客戶端連接的處理,相當(dāng)于BIO的accept
              b.childHandler(new ChannelInitializer<SocketChannel>() {
                  @Override
                  protected void initChannel(SocketChannel sc) throws Exception {
                      log.info("a client connected:{}", sc);
                      sc.pipeline().addLast(new MyChildHandler());
                  }
              });
              b.bind(8888).sync();
          }
      }
      
      @Slf4j
      class MyChildHandler extends ChannelInboundHandlerAdapter {
          @Override
          public void channelActive(ChannelHandlerContext ctx) throws Exception {
              ChatServer.clients.add(ctx.channel());
          }
      
          /**
           * 讀取客戶端通道內(nèi)的數(shù)據(jù)
           * @param msg 客戶端消息
           * @throws Exception
           */
          @Override
          public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
              ByteBuf buf = (ByteBuf) msg;
              String str = buf.toString(StandardCharsets.UTF_8);
              log.info("channelRead().input,string:{},buf:{}", str, buf);
              if (StrUtil.equalsIgnoreCase(str, "__88__")) {
                  ChatServer.clients.remove(ctx.channel());
                  ctx.close();
                  log.info("The chat client has been closed:{}", ctx.channel());
              } else {
                  ChatServer.clients.writeAndFlush(msg);
                  log.info("ChatServer.clients.writeAndFlush:{}", msg);
              }
          }
      
          /**
           * 異常處理
           *
           * @param ctx
           * @param cause
           * @throws Exception
           */
          @Override
          public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
              log.error("exceptionCaught:", cause);
              ChatServer.clients.remove(ctx.channel());
              ctx.close();
          }
      }
      
    5. 補(bǔ)充服務(wù)端關(guān)閉的處理(僅思路,未實現(xiàn))。

      1. 通知客戶端,服務(wù)器準(zhǔn)備關(guān)閉。
      2. 拒絕新的連接接入
      3. 等待所有客戶端都處理完成。
      4. 開始關(guān)閉流程,發(fā)送消息給客戶端,客戶端自動處理。
      5. 確認(rèn)所有客戶端斷開。
      6. server保存現(xiàn)有的工作數(shù)據(jù)。
      7. 停止線程組
      8. 退出。
    6. 服務(wù)端UI

      1. 為了可以方便的看到所有客戶端的連接情況和消息,以及后續(xù)進(jìn)一步實現(xiàn)服務(wù)端的關(guān)閉效果考慮在服務(wù)端實現(xiàn)UI

      2. 新增一個ServerFrame類,實現(xiàn)服務(wù)端UI,服務(wù)端左邊顯示消息,右邊顯示客戶端的連接情況。

      3. ServerFrame類初始化時自動啟動服務(wù)端。服務(wù)端接收消息時打印到消息窗口中。

      4. 有客戶端連上或者關(guān)閉時顯示到右邊的窗口中。

      5. 實現(xiàn)效果如下圖

      6. Netty簡易聊天室,Java,Netty,java

      7. 參考代碼如下。(只需要修改服務(wù)端代碼,客戶端不變)

      8. @Slf4j
        public class ServerFrame extends Frame {
            public static final int GAME_WIDTH = ConfigUtil.getInt("server.frame.width");
            public static final int GAME_HEIGHT = ConfigUtil.getInt("server.frame.height");
            TextArea tmsg = new TextArea("messages:");
            TextArea tclient = new TextArea("clients:");
        
            public static final ServerFrame INSTANCE = new ServerFrame();
        
            public static void main(String[] args) throws Exception {
                INSTANCE.setVisible(true);
                ChatServer.start();
            }
        
            private ServerFrame() throws HeadlessException {
                //創(chuàng)建游戲的主Frame
                this.setTitle("chat room");
                this.setSize(GAME_WIDTH, GAME_HEIGHT);
                this.setLocation(100, 100);
        
                tmsg.setFont(new Font("Calibri",Font.PLAIN,20));
                tclient.setFont(new Font("Calibri",Font.PLAIN,20));
        
                Panel p = new Panel(new GridLayout(1, 2));
                p.add(tmsg);
                p.add(tclient);
                this.add(p);
        
                this.addWindowListener(new WindowAdapter() {
                    @Override
                    public void windowClosing(WindowEvent e) {
                        System.exit(0);
                    }
                });
                log.info("Server Main frame initialization completed");
            }
        
            public void updateMsg(String text) {
                tmsg.setText(tmsg.getText() + Constants.LINE_SEPERATOR + text);
            }
        
            public void updateClient(String text) {
                tclient.setText(tclient.getText() + Constants.LINE_SEPERATOR + text);
            }
        }
        
        @Slf4j
        public class ChatServer {
            static ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
        
            public static void start(){
                //總管線程組
                EventLoopGroup bossGroup = new NioEventLoopGroup(1);
                //接待員線程
                EventLoopGroup workerGroup = new NioEventLoopGroup(2);
                try {
                    //服務(wù)器啟動輔助類
                    ServerBootstrap b = new ServerBootstrap();
                    //放在第一位的是總管線程組,第二位的就是接待員線程組。
                    b.group(bossGroup, workerGroup);
                    //異步全雙工
                    b.channel(NioServerSocketChannel.class);
                    //接收到客戶端連接的處理,相當(dāng)于BIO的accept
                    b.childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel sc) throws Exception {
                            log.info("a client connected:{}", sc);
                            sc.pipeline().addLast(new MyChildHandler());
                        }
                    });
                    log.info("chat server has been started");
                    ChannelFuture cf = b.bind(8888).sync();
                    cf.channel().closeFuture().sync();
                } catch (Exception e) {
                    log.error("ChatServer.exception", e);
                } finally {
                    bossGroup.shutdownGracefully();
                    workerGroup.shutdownGracefully();
                    log.info("chat server has been closed");
                }
            }
        }
        
        @Slf4j
        class MyChildHandler extends ChannelInboundHandlerAdapter {
            @Override
            public void channelActive(ChannelHandlerContext ctx) throws Exception {
                ServerFrame.INSTANCE.updateClient("client connected:"+ctx.channel().remoteAddress());
                ChatServer.clients.add(ctx.channel());
            }
        
            /**
             * 讀取客戶端通道內(nèi)的數(shù)據(jù)
             *
             * @param msg 客戶端消息
             * @throws Exception
             */
            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                ByteBuf buf = (ByteBuf) msg;
                String str = buf.toString(StandardCharsets.UTF_8);
                log.info("channelRead().input,string:{},buf:{}", str, buf);
                if (StrUtil.equalsIgnoreCase(str, "__88__")) {
                    ChatServer.clients.remove(ctx.channel());
                    ctx.close();
                    ServerFrame.INSTANCE.updateClient("client closed>"+ctx.channel().remoteAddress());
                    log.info("The chat client has been closed:{}", ctx.channel());
                } else {
                    ChatServer.clients.writeAndFlush(msg);
                    ServerFrame.INSTANCE.updateMsg(ctx.channel().remoteAddress() + ">" + str);
                    log.info("ChatServer.clients.writeAndFlush:{}", msg);
                }
            }
        
            /**
             * 異常處理
             *
             * @param ctx
             * @param cause
             * @throws Exception
             */
            @Override
            public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
                log.error("ChatServer.exceptionCaught:", cause);
                ChatServer.clients.remove(ctx.channel());
                ctx.close();
            }
        }
        
      9. 啟動順序。先啟動ServerFrame,然后啟動ChatFrame,ChatFrame可以啟動多個。

      10. 多個客戶端發(fā)送消息都會在服務(wù)端顯示。

參考說明

本文內(nèi)容主要來源于馬士兵老師的視頻教程(Java經(jīng)典實戰(zhàn)項目-坦克大戰(zhàn)),結(jié)合了老師的講課內(nèi)容以及自己的實踐做了一些補(bǔ)充。文章來源地址http://www.zghlxwxcb.cn/news/detail-679666.html

到了這里,關(guān)于Netty簡易聊天室的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【 基于Netty實現(xiàn)聊天室聊天業(yè)務(wù)學(xué)習(xí)】第4節(jié).什么是BIO與NIO

    【 基于Netty實現(xiàn)聊天室聊天業(yè)務(wù)學(xué)習(xí)】第4節(jié).什么是BIO與NIO

    IO在讀寫的時候是阻塞的,無法做其他操作,并發(fā)處理能力的非常低,線程之間訪問資源通信時候也是非常耗時久,依賴我們的網(wǎng)速,帶寬。 我們看一下他的白話原理 我們來看一下這張圖那么這張圖的話它里面有一個server還有三個客戶端那么客戶端的話它可以有很多,那么我

    2024年04月26日
    瀏覽(40)
  • LinuxC TCP實現(xiàn)簡易聊天室

    LinuxC TCP實現(xiàn)簡易聊天室

    目錄 1.概述 1.1聊天室設(shè)計內(nèi)容 2.系統(tǒng)設(shè)計 2.1系統(tǒng)功能設(shè)計 2.1.1用戶管理 2.1.2聊天室管理 2.1.3聊天管理 2.2系統(tǒng)數(shù)據(jù)結(jié)構(gòu)設(shè)計 2.3系統(tǒng)主要函數(shù)設(shè)計 3.系統(tǒng)實現(xiàn) 3.2功能模塊的程序流程圖及運(yùn)行界面 3.2.1功能模塊流程圖 ?3.2.2運(yùn)行界面 4.源代碼 4.1客戶端 4.2服務(wù)器 注:存在問題 1

    2024年02月09日
    瀏覽(19)
  • 基于netty+springCloudGateWay+nacos 實現(xiàn)的聊天室(可支持集群)

    基于netty+springCloudGateWay+nacos 實現(xiàn)的聊天室(可支持集群)

    1.基于需要實現(xiàn)一個IM 就記錄一下 。 1.將websocket 注冊到 nacos 服務(wù)上 也是IM 注冊到nacos 上? 借助rabbitmq 實現(xiàn)集群以及redis 實現(xiàn)記錄離線消息具體看代碼文字懶得寫(里面自己還嘗試換了 zookeeper 作為注冊中心 僅供學(xué)習(xí))IM 和 網(wǎng)關(guān)的 目錄: 整個邏輯是啟動服務(wù)將websocket,網(wǎng)關(guān)

    2023年04月08日
    瀏覽(18)
  • 【Java socket編程】多人聊天室

    【Java socket編程】多人聊天室

    課程設(shè)計大作業(yè) 功能: 1.具有 點對點通信 功能,任意客戶端之間能夠發(fā)送消息。 2.具有 群組通信 功能: 客戶端可以 自主建立群組 ,添加或刪除組成員; 客戶端能夠向組內(nèi)成員同時發(fā)送消息,其他組成員不能收到。 3.具有 廣播 功能 客戶端能夠向所有其他成員 廣播消息

    2024年02月04日
    瀏覽(35)
  • Java+Vue實現(xiàn)聊天室(WebSocket進(jìn)階-聊天記錄)

    Java+Vue實現(xiàn)聊天室(WebSocket進(jìn)階-聊天記錄)

    WebSocket 是一種在單個TCP連接上進(jìn)行全雙工通信的協(xié)議。WebSocket通信協(xié)議于2011年被IETF定為標(biāo)準(zhǔn)RFC 6455,并由RFC7936補(bǔ)充規(guī)范。WebSocket API也被W3C定為標(biāo)準(zhǔn)。 WebSocket使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡單,允許服務(wù)端主動向客戶端推送數(shù)據(jù)。在WebSocket API中,瀏覽器和服

    2024年02月11日
    瀏覽(111)
  • Spring boot 項目(二十三)——用 Netty+Websocket實現(xiàn)聊天室

    Spring boot 項目(二十三)——用 Netty+Websocket實現(xiàn)聊天室

    Netty 是基于 Java NIO 的異步事件驅(qū)動的網(wǎng)絡(luò)應(yīng)用框架,使用 Netty 可以快速開發(fā)網(wǎng)絡(luò)應(yīng)用,Netty 提供了高層次的抽象來簡化 TCP 和 UDP 服務(wù)器的編程,但是你仍然可以使用底層的 API。 Netty 的內(nèi)部實現(xiàn)是很復(fù)雜的,但是 Netty 提供了簡單易用的API從網(wǎng)絡(luò)處理代碼中解耦業(yè)務(wù)邏輯。

    2023年04月15日
    瀏覽(88)
  • websocket+elementui+vue實現(xiàn)簡易聊天室

    websocket+elementui+vue實現(xiàn)簡易聊天室

    搭建服務(wù)端環(huán)境 安裝socket.io 服務(wù)端基于node,js的express框架生成,所以寫成模塊,引入至app.js中 其中,io.sockets.emit用于向所有建立連接的客戶端發(fā)送信息,socket.broadcast.emit用于向除發(fā)送方之外的客戶端發(fā)送信息。 客戶端基于vue和elementui 進(jìn)入聊天頁面后,先判斷用戶是否登錄,

    2024年04月25日
    瀏覽(37)
  • 基于springboot與websocket實現(xiàn)簡易聊天室

    基于springboot與websocket實現(xiàn)簡易聊天室

    創(chuàng)建一個簡單聊天室的HTML和JavaScript代碼,匹配相應(yīng)的css樣式,這個聊天室將使用WebSocket技術(shù),允許用戶實時發(fā)送和接收消息。 1.1 html和js代碼 通過new WebSocket(url)建立一個新的websocket連接。websocket連接建立之后使用websocket.onopen,websocket.onclose,websocket.onerror等方法實時監(jiān)測we

    2024年02月01日
    瀏覽(26)
  • 基于java的聊天室系統(tǒng)設(shè)計與實現(xiàn)

    基于java的聊天室系統(tǒng)設(shè)計與實現(xiàn) 研究背景: 隨著互聯(lián)網(wǎng)技術(shù)的迅速發(fā)展和普及,在線聊天和實時通信成為人們?nèi)粘=涣鞯闹匾绞健A奶焓蚁到y(tǒng)作為實時通信的一種重要形式,具有廣泛的應(yīng)用場景,如遠(yuǎn)程教育、在線游戲、即時通訊、網(wǎng)絡(luò)直播等。因此,設(shè)計和實現(xiàn)一個基

    2024年02月05日
    瀏覽(20)
  • 基于WebSocket的簡易聊天室的基本實現(xiàn)梳理

    基于WebSocket的簡易聊天室的基本實現(xiàn)梳理

    目前在很多網(wǎng)站為了實現(xiàn)推送技術(shù)所用的技術(shù)都是 Ajax 輪詢。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對服務(wù)器發(fā)出HTTP請求,然后由服務(wù)器返回最新的數(shù)據(jù)給客戶端的瀏覽器。HTTP 協(xié)議是一種無狀態(tài)的、無連接的、單向的應(yīng)用層協(xié)議。它采用了請求/響應(yīng)模型。通信

    2024年02月11日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包