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

netty-發(fā)起tcp長(zhǎng)連接(包含客戶端和服務(wù)端)

這篇具有很好參考價(jià)值的文章主要介紹了netty-發(fā)起tcp長(zhǎng)連接(包含客戶端和服務(wù)端)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

Netty是一個(gè)高性能、異步事件驅(qū)動(dòng)的NIO框架,它提供了對(duì)TCP、UDP和文件傳輸?shù)闹С帧?/p>

Netty是對(duì)JDK自帶的NIO的API進(jìn)行封裝,具有高并發(fā),高性能等優(yōu)點(diǎn)。

項(xiàng)目中經(jīng)常用到netty實(shí)現(xiàn)服務(wù)器與設(shè)備的通信,先寫(xiě)服務(wù)端代碼:

@Slf4j
@Component
public class NettyServerBootstrap {

    private Channel serverChannel;
    private static final int DEFAULT_PORT = 60782;
    //bossGroup只是處理連接請(qǐng)求
    private static EventLoopGroup bossGroup = null;
    //workGroup處理非連接請(qǐng)求,如果牽扯到數(shù)據(jù)量處理業(yè)務(wù)非常耗時(shí)的可以再單獨(dú)新建一個(gè)eventLoopGroup,并在childHandler初始化的時(shí)候添加到pipeline綁定
    private static EventLoopGroup workGroup = null;

    /**
     * 啟動(dòng)Netty服務(wù)
     *
     * @return 啟動(dòng)結(jié)果
     */
    @PostConstruct
    public boolean start() {
        bossGroup = new NioEventLoopGroup();
        workGroup = new NioEventLoopGroup();
        //創(chuàng)建服務(wù)端啟動(dòng)對(duì)象
        ServerBootstrap bootstrap = new ServerBootstrap();
        try {
            //使用鏈?zhǔn)骄幊虂?lái)設(shè)置
            bootstrap.group(bossGroup, workGroup)//設(shè)置兩個(gè)線程組
                    //使用NioSocketChannel作為服務(wù)器的通道實(shí)現(xiàn)
                    .channel(NioServerSocketChannel.class)
                    //設(shè)置線程隊(duì)列得到的連接數(shù)
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    //設(shè)置保持活動(dòng)連接狀態(tài)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    //設(shè)置處理器  WorkerGroup 的 EvenLoop 對(duì)應(yīng)的管道設(shè)置處理器
                    .childHandler(new ChannelInitializer<Channel>() {

                        @Override
                        protected void initChannel(Channel ch){
                            log.info("--------------有客戶端連接");
                            ch.pipeline().addLast(new StringDecoder());
                            ch.pipeline().addLast(new StringEncoder());
                            ch.pipeline().addLast(new NettyServerHandler());
                        }
                    });
            //綁定端口, 同步等待成功;
            ChannelFuture future = bootstrap.bind(DEFAULT_PORT).sync();
            log.info("netty服務(wù)啟動(dòng)成功,ip:{},端口:{}", InetAddress.getLocalHost().getHostAddress(), DEFAULT_PORT);
            serverChannel = future.channel();
            ThreadUtil.execute(() -> {
                //等待服務(wù)端監(jiān)聽(tīng)端口關(guān)閉
                try {
                    future.channel().closeFuture().sync();
                    log.info("netty服務(wù)正常關(guān)閉成功,ip:{},端口:{}", InetAddress.getLocalHost().getHostAddress(), DEFAULT_PORT);
                } catch (InterruptedException | UnknownHostException e) {
                    e.printStackTrace();
                } finally {
                    shutdown();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            log.error("netty服務(wù)異常,異常原因:{}", e.getMessage());
            return false;
        }
        return true;
    }


    /**
     * 關(guān)閉當(dāng)前server
     */
    public boolean close() {
        if (serverChannel != null) {
            serverChannel.close();//關(guān)閉服務(wù)
            try {
                //保險(xiǎn)起見(jiàn)
                serverChannel.closeFuture().sync();
            } catch (InterruptedException e) {
                e.printStackTrace();
                return false;
            } finally {
                shutdown();
                serverChannel = null;
            }
        }
        return true;
    }

    /**
     * 優(yōu)雅關(guān)閉
     */
    private void shutdown() {
        workGroup.shutdownGracefully();
        bossGroup.shutdownGracefully();
    }

}

服務(wù)端處理類代碼:

@Slf4j
public class NettyServerHandler extends SimpleChannelInboundHandler<String> {

    /**
     * 處理讀取到的msg
     *
     * @param ctx 上下文
     * @param msg 數(shù)據(jù)
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx,String msg) throws Exception {
        System.out.println("服務(wù)端收到的消息--------"+msg);
        ctx.channel().writeAndFlush("ok");
    }

    /**
     * 斷開(kāi)連接
     *
     * @param ctx 傻瓜下文
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        ChannelId channelId = ctx.channel().id();
        log.info("客戶端id:{},斷開(kāi)連接,ip:{}", channelId, ctx.channel().remoteAddress());
        super.handlerRemoved(ctx);
    }

}

接下來(lái)模擬客戶端:

@Configuration
@Component
public class TianmiaoClient {


    private static String ip;

    private static int port ;

    @Value("${tianmiao.nettyServer.ip}")
    public void setIp(String ip) {
        this.ip = ip;
    }

    @Value("${tianmiao.nettyServer.port}")
    public void setPort(int port) {
        this.port = port;
    }

    /**
     * 服務(wù)類
     */
    private static Bootstrap bootstrap=null;

    /**
     * 初始化  項(xiàng)目啟動(dòng)后自動(dòng)初始化
     */
    @PostConstruct
    public void init() {

        //worker
        EventLoopGroup worker = new NioEventLoopGroup();

        bootstrap = new Bootstrap();
        //設(shè)置線程池
        bootstrap.group(worker);

        //設(shè)置socket工廠
        bootstrap.channel(NioSocketChannel.class);

        //設(shè)置管道
        bootstrap.handler(new ChannelInitializer<Channel>() {

            @Override
            protected void initChannel(Channel ch) throws Exception {
                ch.pipeline().addLast(new StringDecoder());
                ch.pipeline().addLast(new StringEncoder());
                ch.pipeline().addLast(new TianmiaoClientHandler());
            }
        });
    }


    /**
     * 獲取會(huì)話 (獲取或者創(chuàng)建一個(gè)會(huì)話)
     */
    public Channel createChannel() {
        try {
            Channel channel = bootstrap.connect( ip, port).sync().channel();
            return channel;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}

客戶端處理類代碼

public class TianmiaoClientHandler extends SimpleChannelInboundHandler<String> {

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
        System.out.println("服務(wù)端發(fā)過(guò)來(lái)的消息:"+s);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println(".......................tcp斷開(kāi)連接.........................");
        //移除
        Channel channel = ctx.channel();
        channel.close().sync();
        super.channelInactive(ctx);
    }

}

管理客戶端channel的一個(gè)工具類:

public class TianmiaoChannelManager {

    /**
     * 在線會(huì)話(存儲(chǔ)注冊(cè)成功的會(huì)話)
     */
    private static final ConcurrentHashMap<String, Channel> onlineChannels = new ConcurrentHashMap<>();


    /**
     * 加入
     *
     * @param mn
     * @param channel
     * @return
     */
    public static boolean putChannel(String mn, Channel channel) {
        if (!onlineChannels.containsKey(mn)) {
            boolean success = onlineChannels.putIfAbsent(mn, channel) == null ? true : false;
            return success;
        }
        return false;
    }

    /**
     * 移除
     *
     * @param mn
     */
    public static Channel removeChannel(String mn) {
        return onlineChannels.remove(mn);
    }

    /**
     * 獲取Channel
     *
     * @param mn
     * @return
     */
    public static Channel getChannel(String mn) {
        // 獲取一個(gè)可用的會(huì)話
        Channel channel = onlineChannels.get(mn);
        if (channel != null) {
            // 連接有可能是斷開(kāi),加入已經(jīng)斷開(kāi)連接了,我們需要進(jìn)行嘗試重連
            if (!channel.isActive()) {
                //先移除之前的連接
                removeChannel(mn);
                return null;
            }
        }
        return channel;
    }

    /**
     * 發(fā)送消息[自定義協(xié)議]
     *
     * @param <T>
     * @param mn
     * @param msg
     */
    public static <T> void sendMessage(String mn, String msg) {
        Channel channel = onlineChannels.get(mn);
        if (channel != null && channel.isActive()) {
            channel.writeAndFlush(msg);
        }
    }

    /**
     * 發(fā)送消息[自定義協(xié)議]
     *
     * @param <T>
     * @param msg
     */
    public static <T> void sendChannelMessage(Channel channel, String msg) {
        if (channel != null && channel.isActive()) {
            channel.writeAndFlush(msg);
        }
    }

    /**
     * 關(guān)閉連接
     *
     * @return
     */
    public static void closeChannel(String mn) {
        onlineChannels.get(mn).close();
    }
}

最后是客戶端使用方法:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-660890.html

/**
 * 發(fā)送數(shù)據(jù)包
 * @param key
 */
public static void tianmiaoData(String key, String data) {
    Channel channel = TianmiaoChannelManager.getChannel(key);
    //將通道存入
    if(channel==null){
        TianmiaoClient client = new TianmiaoClient();
        channel = client.createChannel();
        TianmiaoChannelManager.putChannel(key, channel);
    }
    if (channel != null && channel.isActive()) {
        //發(fā)送數(shù)據(jù)
        channel.writeAndFlush(data);
        System.out.println("-------------天苗轉(zhuǎn)發(fā)數(shù)據(jù)成功-------------");
    }
}

到了這里,關(guān)于netty-發(fā)起tcp長(zhǎng)連接(包含客戶端和服務(wù)端)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

  • 32.Netty源碼之服務(wù)端如何處理客戶端新建連接

    32.Netty源碼之服務(wù)端如何處理客戶端新建連接

    Netty 服務(wù)端完全啟動(dòng)后,就可以對(duì)外工作了。接下來(lái) Netty 服務(wù)端是如何處理客戶端新建連接的呢? 主要分為四步: md Boss NioEventLoop 線程輪詢客戶端新連接 OP_ACCEPT 事件; ? 構(gòu)造 初始化Netty 客戶端 NioSocketChannel; ? 注冊(cè) Netty 客戶端 NioSocketChannel 到 Worker 工作線程中; ? 從

    2024年02月12日
    瀏覽(19)
  • SpringBoot中使用Netty實(shí)現(xiàn)TCP通訊,服務(wù)器主動(dòng)向客戶端發(fā)送數(shù)據(jù)

    SpringBoot中使用Netty實(shí)現(xiàn)TCP通訊,服務(wù)器主動(dòng)向客戶端發(fā)送數(shù)據(jù)

    Springboot項(xiàng)目的web服務(wù)后臺(tái),web服務(wù)運(yùn)行在9100端口。 后臺(tái)使用netty實(shí)現(xiàn)了TCP服務(wù),運(yùn)行在8000端口。 啟動(dòng)截圖如下: 啟動(dòng)類修改: 服務(wù)器查看當(dāng)前所有連接的客戶端 ?服務(wù)器獲取到所有客戶單的ip地址及端口號(hào)后,即可通過(guò)其給指定客戶端發(fā)送數(shù)據(jù) ?

    2024年02月11日
    瀏覽(29)
  • tcp服務(wù)器端與多個(gè)客戶端連接

    tcp服務(wù)器端與多個(gè)客戶端連接

    如果希望Tcp服務(wù)器端可以與多個(gè)客戶端連接,可以這樣寫(xiě): 相關(guān)的槽函數(shù)中: 使用sender()來(lái)獲取對(duì)應(yīng)的QTcpSocket對(duì)象。 其實(shí),主要就是QTcpServer進(jìn)行監(jiān)聽(tīng): 客戶端的QTcpSocket與服務(wù)器端的QTcpSocket進(jìn)行通信。

    2024年04月28日
    瀏覽(48)
  • java socket Server TCP服務(wù)端向指定客戶端發(fā)送消息;可查看、斷開(kāi)指定連接的客戶端;以及設(shè)置客戶端最大可連接數(shù)量。

    首先需要知道java里如何創(chuàng)建一個(gè)Socket服務(wù)器端。 提示:注意server.accept()方法調(diào)用會(huì)阻塞,只有新的客戶端連接后才返回一個(gè)新的socket對(duì)象。如果一直未連接那么會(huì)一直處于阻塞狀態(tài) 了解了如何創(chuàng)建一個(gè)socket服務(wù)器端后。那么如何實(shí)現(xiàn)給指定的連接客戶端發(fā)送消息呢?首先我

    2024年02月11日
    瀏覽(24)
  • tcp連接斷開(kāi)分析,判斷tcp斷開(kāi)原因是客戶端還是服務(wù)端?

    tcp連接斷開(kāi)分析,判斷tcp斷開(kāi)原因是客戶端還是服務(wù)端?

    ? ? ? ? ? 當(dāng)與使用TCP協(xié)議對(duì)接的硬件設(shè)備進(jìn)行通信時(shí),往往會(huì)遇到一些問(wèn)題,導(dǎo)致一些人難以找到tcp斷開(kāi)的根源,因些無(wú)法判定是充電樁設(shè)備客戶端還是服務(wù)器端。我曾經(jīng)在十多年前對(duì)接銀行接口的POS機(jī)時(shí)遇到過(guò)類似的情況,現(xiàn)在在對(duì)接充電樁時(shí)又遇到了相似的問(wèn)題。經(jīng)過(guò)

    2024年02月03日
    瀏覽(33)
  • TCP服務(wù)器最多支持多少客戶端連接

    TCP服務(wù)器最多支持多少客戶端連接

    目錄 一、理論數(shù)值 二、實(shí)際部署 ?參考 ????????首先知道一個(gè)基礎(chǔ)概念,對(duì)于一個(gè) TCP 連接可以使用四元組(src_ip, src_port, dst_ip, dst_port)進(jìn)行唯一標(biāo)識(shí)。因?yàn)榉?wù)端 IP 和 Port 是固定的(如下圖中的bind階段),那么一個(gè)TCP服務(wù)器支持最多的連接數(shù)就是由客戶端 IP 和 端口

    2024年01月21日
    瀏覽(31)
  • Golang實(shí)現(xiàn)之TCP長(zhǎng)連接-------服務(wù)端和客戶端

    一、數(shù)據(jù)包的數(shù)據(jù)結(jié)構(gòu) (所有字段采用大端序) 幀頭 幀長(zhǎng)度(頭至尾) 幀類型 幀數(shù)據(jù) 幀尾 1字節(jié) 4字節(jié) 2字節(jié) 1024字節(jié) 1字節(jié) byte int short string byte 0xC8 0xC9 二、Server端?實(shí)現(xiàn)代碼 1、main.go 2、server.go 3、protocol.go 4、response.go 5、result.go 三、Client端?實(shí)現(xiàn)代碼

    2024年02月07日
    瀏覽(23)
  • Python啟動(dòng)TCP服務(wù)并監(jiān)聽(tīng)連接,從客戶端發(fā)送消息

    Python啟動(dòng)TCP服務(wù)并監(jiān)聽(tīng)連接,從客戶端發(fā)送消息

    下面是一個(gè)簡(jiǎn)單的例子,演示如何在Python中啟動(dòng)TCP服務(wù)并監(jiān)聽(tīng)連接,以及如何從客戶端發(fā)送消息: TCP服務(wù)端代碼: TCP客戶端代碼: 這個(gè)例子中,服務(wù)端首先創(chuàng)建一個(gè)socket對(duì)象并綁定地址和端口,然后開(kāi)始監(jiān)聽(tīng)連接。當(dāng)客戶端連接到服務(wù)器時(shí),服務(wù)端接受客戶端的連接請(qǐng)求并

    2024年02月13日
    瀏覽(18)
  • TCP客戶端判斷與服務(wù)端斷開(kāi)連接的幾種方法

    目前已知的方法有: 1、 epoll(能檢測(cè)正常的斷開(kāi)連接,事件觸發(fā)機(jī)制,優(yōu)點(diǎn)是快速,但是插拔網(wǎng)線是檢測(cè)不到的) 2、自定義心跳包方式檢測(cè) 3、keeplive方式檢測(cè) 4、getsockopt 1、相對(duì)于select和poll來(lái)說(shuō),epoll更加靈活,沒(méi)有描述符限制。epoll使用一個(gè)文件描述符管理多個(gè)描述符,

    2023年04月14日
    瀏覽(31)
  • Socket實(shí)例,實(shí)現(xiàn)多個(gè)客戶端連接同一個(gè)服務(wù)端代碼&TCP網(wǎng)絡(luò)編程 ServerSocket和Socket實(shí)現(xiàn)多客戶端聊天

    Socket實(shí)例,實(shí)現(xiàn)多個(gè)客戶端連接同一個(gè)服務(wù)端代碼&TCP網(wǎng)絡(luò)編程 ServerSocket和Socket實(shí)現(xiàn)多客戶端聊天

    Java socket(套接字)通常也稱作\\\"套接字\\\",用于描述ip地址和端口,是一個(gè)通信鏈的句柄。應(yīng)用程序通常通過(guò)\\\"套接字\\\"向網(wǎng)絡(luò)發(fā)出請(qǐng)求或者應(yīng)答網(wǎng)絡(luò)請(qǐng)求。 使用socket實(shí)現(xiàn)多個(gè)客戶端和同一客戶端通訊;首先客戶端連接服務(wù)端發(fā)送一條消息,服務(wù)端接收到消息后進(jìn)行處理,完成后再

    2024年02月12日
    瀏覽(89)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包