国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

netty搭建web聊天室(1)

izhuhaodev / 3342人閱讀

摘要:提供異步的事件驅(qū)動的網(wǎng)絡(luò)應(yīng)用程序框架和工具,用以快速開發(fā)高性能高可靠性的網(wǎng)絡(luò)服務(wù)器和客戶端程序。總結(jié)我們完成了服務(wù)端的簡單搭建,模擬了聊天會話場景。

之前一直在搞前端的東西,都快忘了自己是個(gè)java開發(fā)。其實(shí)還有好多java方面的東西沒搞過,突然了解到netty,覺得有必要學(xué)一學(xué)。
介紹

Netty是由JBOSS提供的一個(gè)java開源框架。Netty提供異步的、事件驅(qū)動的網(wǎng)絡(luò)應(yīng)用程序框架和工具,用以快速開發(fā)高性能、高可靠性的網(wǎng)絡(luò)服務(wù)器和客戶端程序。

也就是說,Netty 是一個(gè)基于NIO的客戶、服務(wù)器端編程框架,使用Netty 可以確保你快速和簡單的開發(fā)出一個(gè)網(wǎng)絡(luò)應(yīng)用,例如實(shí)現(xiàn)了某種協(xié)議的客戶、服務(wù)端應(yīng)用。Netty相當(dāng)于簡化和流線化了網(wǎng)絡(luò)應(yīng)用的編程開發(fā)過程,例如:基于TCP和UDP的socket服務(wù)開發(fā)。

一些IO概念

NIO (non-blocking IO) 非阻塞

BIO (blocking IO) 阻塞

以上兩種又可分為同步和異步,即同步阻塞,同步非阻塞,異步阻塞,異步非阻塞。

阻塞:數(shù)據(jù)沒來,啥都不做,直到數(shù)據(jù)來了,才進(jìn)行下一步的處理。

非阻塞:數(shù)據(jù)沒來,進(jìn)程就不停的去檢測數(shù)據(jù),直到數(shù)據(jù)來。

至于這塊的詳細(xì)概念,大家可以自行百度學(xué)習(xí)。總之,netty處理io很高效,不需要你擔(dān)心。

netty結(jié)構(gòu)

可以看出它支持的網(wǎng)絡(luò)傳輸協(xié)議,以及容器支持,安全支持,io.

工作流程:
所有客戶端的連接交給住主線程去管理,響應(yīng)客戶端的消息交給從線程去處理,整個(gè)線程池由netty負(fù)責(zé)。

搭建服務(wù)

創(chuàng)建maven工程引入最新的依賴


    4.0.0
    com.mike
    netty
    0.0.1-SNAPSHOT

    
        UTF-8
        1.8
    

    
        
            io.netty
            netty-all
            4.1.32.Final
        
    

創(chuàng)建消息處理器

package netty;

import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http2.Http2Headers;
import io.netty.util.concurrent.GlobalEventExecutor;

/**
 * 
 */
public class ChatHandler extends SimpleChannelInboundHandler{
    
    public static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    
    /**
     * 每當(dāng)從服務(wù)端收到新的客戶端連接時(shí),客戶端的 Channel 存入ChannelGroup列表中,并通知列表中的其他客戶端 Channel
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {  
        Channel incoming = ctx.channel();
        for (Channel channel : channels) {
            channel.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " 加入
");
        }
        channels.add(ctx.channel());
    }
    
    /**
     * 每當(dāng)從服務(wù)端收到客戶端斷開時(shí),客戶端的 Channel 移除 ChannelGroup 列表中,并通知列表中的其他客戶端 Channel
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {  
        Channel incoming = ctx.channel();
        for (Channel channel : channels) {
            channel.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " 離開
");
        }
        channels.remove(ctx.channel());
    }
    
    /**
     * 會話建立時(shí)
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception { // (5)
        Channel incoming = ctx.channel();
        System.out.println("ChatClient:"+incoming.remoteAddress()+"在線");
    }
    
    /**
     * 會話結(jié)束時(shí)
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception { // (6)
        Channel incoming = ctx.channel();
        System.out.println("ChatClient:"+incoming.remoteAddress()+"掉線");
    }
    
    /**
     * 出現(xiàn)異常
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (7)
        Channel incoming = ctx.channel();
        System.out.println("ChatClient:"+incoming.remoteAddress()+"異常");
        // 當(dāng)出現(xiàn)異常就關(guān)閉連接
        cause.printStackTrace();
        ctx.close();
    }
    
    /**
     * 讀取客戶端發(fā)送的消息,并將信息轉(zhuǎn)發(fā)給其他客戶端的 Channel。
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object  request) throws Exception {
            FullHttpResponse response = new DefaultFullHttpResponse(
                    HttpVersion.HTTP_1_1,HttpResponseStatus.OK , Unpooled.wrappedBuffer("Hello netty"
                            .getBytes()));
            response.headers().set("Content-Type", "text/plain");
            response.headers().set("Content-Length", response.content().readableBytes());
            response.headers().set("connection", HttpHeaderValues.KEEP_ALIVE);
            ctx.writeAndFlush(response);
        
    }

}

這里面其實(shí)只需要重寫channelRead0 方法就可以了,其他是它的生命周期的方法,可以用來做日至記錄。我們在讀取消息后,往channel里寫入了一個(gè)http的response。

初始化我們的消息處理器

package netty;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;

/**
 * 用來增加多個(gè)的處理類到 ChannelPipeline 上,包括編碼、解碼、SimpleChatServerHandler 等。
 */
public class ChatServerInitializer extends ChannelInitializer{

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
            ChannelPipeline pipeline = ch.pipeline();
            pipeline.addLast("HttpResponseEncoder",new HttpResponseEncoder());
            pipeline.addLast("HttpRequestDecoder",new HttpRequestDecoder());
            pipeline.addLast("chathandler", new ChatHandler());

            System.out.println("ChatClient:"+ch.remoteAddress() +"連接上");
        
    }

}

這個(gè)pipeline可以理解為netty的攔截器,每個(gè)消息進(jìn)來,經(jīng)過各個(gè)攔截器的處理。我們需要響應(yīng)http消息,所以加入了響應(yīng)編碼以及請求解碼,最后加上了我們的自定義處理器。這里面有很多處理器,netty以及幫你定義好的。

服務(wù)啟動類

package netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * The class ChatServer
 */
public class ChatServer {
      private int port;

        public ChatServer(int port) {
            this.port = port;
        }

        public void run() throws Exception {

            EventLoopGroup bossGroup = new NioEventLoopGroup(); 
            EventLoopGroup workerGroup = new NioEventLoopGroup();
            try {
                ServerBootstrap b = new ServerBootstrap(); 
                b.group(bossGroup, workerGroup)
                 .channel(NioServerSocketChannel.class) 
                 .childHandler(new ChatServerInitializer())  
                 .option(ChannelOption.SO_BACKLOG, 128)          
                 .childOption(ChannelOption.SO_KEEPALIVE, true); 

                System.out.println("ChatServer 啟動了");

                // 綁定端口,開始接收進(jìn)來的連接
                ChannelFuture f = b.bind(port).sync(); // (7)

                // 等待服務(wù)器  socket 關(guān)閉 。
                // 在這個(gè)例子中,這不會發(fā)生,但你可以優(yōu)雅地關(guān)閉你的服務(wù)器。
                f.channel().closeFuture().sync();

            } finally {
                workerGroup.shutdownGracefully();
                bossGroup.shutdownGracefully();

                System.out.println("ChatServer 關(guān)閉了");
            }
        }

        public static void main(String[] args) throws Exception {
            new ChatServer(8090).run();

        }
}

這個(gè)啟動類就是按照上面那個(gè)結(jié)構(gòu)圖來的,添加兩個(gè)線程組,設(shè)置channel,添加消息處理器,配置一些選項(xiàng)option。

測試

啟動程序,瀏覽器訪問 http://localhost:8090

可以在瀏覽器看到我們返回的消息,但是控制臺卻顯示連接了多個(gè)客戶端,其實(shí)是因?yàn)闉g覽器發(fā)送了無關(guān)的請求道服務(wù)端,由于我們沒有做路由,所以所有請求都是200。

可以看到,發(fā)送了兩次請求。現(xiàn)在我們換postman測試。

這次只有一個(gè)客戶端連接,當(dāng)我們關(guān)閉postman:

客戶端顯示掉線,整個(gè)會話過程結(jié)束。

總結(jié)

我們完成了服務(wù)端的簡單搭建,模擬了聊天會話場景。后面再接著完善。

別忘了關(guān)注我 mike啥都想搞

還有其他后端技術(shù)分享在我的公眾號。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/73106.html

相關(guān)文章

  • netty搭建web天室(3)單聊

    摘要:開始聊天發(fā)送聊天信息時(shí)消息,這樣后端就知道是誰要發(fā)給誰,根據(jù)用戶名去找到具體的線程去單獨(dú)推送消息,實(shí)現(xiàn)單聊。前端待完善左側(cè)聊天列表沒有實(shí)現(xiàn),每搜索一個(gè)在線用戶,應(yīng)該動態(tài)顯示在左側(cè),點(diǎn)擊該用戶,動態(tài)顯示右側(cè)聊天窗口進(jìn)行消息發(fā)送。 上節(jié)課講了群聊,這次來說說單聊,單聊要比群聊復(fù)雜點(diǎn),但是代碼也不是很多,主要是前端顯示比較麻煩點(diǎn)。 效果:showImg(https://segmentfaul...

    Lavender 評論0 收藏0
  • netty搭建web天室(2)群聊

    摘要:上節(jié)課完成了的后端搭建,搞定了簡單的請求響應(yīng),今天來結(jié)合前端來完成群聊功能。其實(shí)后端群聊很簡單,就是把一個(gè)用戶的輸入消息,返回給所有在線客戶端,前端去負(fù)責(zé)篩選顯示。 上節(jié)課完成了netty的后端搭建,搞定了簡單的http請求響應(yīng),今天來結(jié)合前端websocket來完成群聊功能。話不多說先上圖:showImg(https://segmentfault.com/img/bVbnCa8?w=...

    microelec 評論0 收藏0
  • 不發(fā)不行!Netty集成文字圖片天室外加TCP/IP軟硬件通信

    摘要:前言熬了一晚上硬是磨出來了,更新到了上,善存一些小,不過這個(gè)版本的整體功能算是實(shí)現(xiàn)了。預(yù)留其余的就是可能善存的一些了圖片過大,需要在前端做圖片上傳壓縮前端代碼的一點(diǎn)問題,不影響項(xiàng)目正常運(yùn)行遠(yuǎn)程主機(jī)強(qiáng)迫關(guān)閉了一個(gè)現(xiàn)有的連接。 前言 熬了一晚上硬是磨出來了,更新到了GitHub上,善存一些小BUG,不過這個(gè)版本的整體功能算是實(shí)現(xiàn)了。 項(xiàng)目:UncleCatMySelf/InChat 地址:...

    siberiawolf 評論0 收藏0
  • 用Java構(gòu)建一個(gè)簡單的WebSocket聊天項(xiàng)目之新增HTTP接口調(diào)度

    摘要:前言大家可以看看上一篇用構(gòu)建一個(gè)簡單的聊天室在上一篇文章中我們已經(jīng)實(shí)現(xiàn)了自我對話好友交流群聊離線消息等的功能。系統(tǒng)通知恭喜您連續(xù)登錄超過天,獎勵(lì)積分。 本文首發(fā)公眾號與個(gè)人博客:Java貓說 & 貓叔的博客 | MySelf,轉(zhuǎn)載請申明出處。 前言 大家可以看看上一篇:用Java構(gòu)建一個(gè)簡單的WebSocket聊天室 在上一篇文章中我們已經(jīng)實(shí)現(xiàn)了:自我對話、好友交流、群聊、離線消息等...

    vvpvvp 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<