【netty】java如何作为websocket客户端 对服务端发起请求

这篇具有很好参考价值的文章主要介绍了【netty】java如何作为websocket客户端 对服务端发起请求。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

是的 本文介绍java如何作为客户端 发起websocket请求
博主不做标题党 不会服务端客户端分不清就写个标题 乱写文章

前言

为什么会使用java作为websocket客户端? 虽说websocket协议 本意是web与服务端之间的通讯协议,那假设有一天 我们的供应商 或者是甲方大爷 只提供了websocket接口呢?
如果直接让前端去对接,再把数据传给后端,那从前端对接到后端入库的步骤,万一出现数据丢失呢? 总之把数据处理放在后端,是相对可靠的, 我们可以借助netty来实现websocket客户端功能

长链接有两点值得注意的,一是心跳机制 二是重连机制
如果不发送心跳包,可能过会儿连接就断开了;
重新机制就比较好理解了,不管是服务端还是客户端的断开,作为客户端都需要能够重连

代码

博主对长链接并不是特别熟练,但是什么代码是能正式用的,什么代码上不了生产只是个写着玩的demo 还是一眼能分辨出来的,代码主要参考 git@github.com:yimiancheng/netty-study.git ,写的很不错,代码优化空间很少了, 线程池博主是推荐用new ThreadPoolExecutor()创建,避免OOM的问题,除此之外应该是准生产环境级别代码了。

maven依赖

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

websocket客户端handle类 主要处理接收的消息、事件等,
事件触发会进入userEventTriggered方法
建立连接会进入channelActive方法
接收消息会进入channelRead0方法
出现异常会进入exceptionCaught方法
断开连接会进入channelInactive方法(本文中未重写该方法, 在channelInactive方法中重连也是没问题的)


import com.qiuhuanhen.springroot.interfaces.websocket.websocketclient.SocketClient;
import com.qiuhuanhen.springroot.interfaces.websocket.websocketclient.websocket.SendMsg;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketClientProtocolHandler;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * WebSocketClientFrameHandler
 *
 * @date 2019/8/20 16:42
 */
public class WebSocketClientFrameHandler extends SimpleChannelInboundHandler<WebSocketFrame> {
    private static final Logger LOG = LoggerFactory.getLogger(WebSocketClientFrameHandler.class);
    private SocketClient socketClient;
    private ChannelPromise channelPromise;

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        LOG.info("客户端接收到事件 " + (evt.getClass()) + " | " + evt.toString());

        if(WebSocketClientProtocolHandler.ClientHandshakeStateEvent.HANDSHAKE_COMPLETE.equals(evt)) {
            LOG.info(ctx.channel().id().asShortText() + " 握手完成!");
            socketClient.CHANNEL_IS_READY.set(true);
            channelPromise.setSuccess();
            // SendMsg.send(ctx.channel(),"客户端握手完成消息 -》服务器时间: " + System.currentTimeMillis());
        }
        else if(evt instanceof IdleStateEvent){
            //ctx.channel().writeAndFlush(new PingWebSocketFrame());
            IdleStateEvent evtIdle = (IdleStateEvent) evt;
            switch(evtIdle.state()) {
                case WRITER_IDLE:
                    // SendMsg.send(ctx.channel(),"客户端 ping 消息 -》服务器时间: " + System.currentTimeMillis());
                    ctx.channel().writeAndFlush(new PingWebSocketFrame());
                case READER_IDLE:
                    // SendMsg.send(ctx.channel(),"客户端 ping 消息 -》服务器时间: " + System.currentTimeMillis());
                    ctx.channel().writeAndFlush(new PingWebSocketFrame());
                default:
                    break;
            }
        }

        super.userEventTriggered(ctx, evt);
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        LOG.info("打开连接 handlerAdded SUCCESS. | name = " +channel.id().asShortText());
        super.handlerAdded(ctx);
        channelPromise = ctx.newPromise();
    }

    /**
     * Channel 已经被注册到了EventLoop
     */
    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        LOG.info("注册成功 channelRegistered SUCCESS. | name = " +channel.id().asShortText());
        super.channelRegistered(ctx);
    }

    /**
     * Channel 处于活动状态(已经连接到它的远程节点)。它现在可以接收和发送数据了
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        LOG.info("活动状态 channelActive SUCCESS. | name = " +channel.id().asShortText());
        super.channelActive(ctx);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, WebSocketFrame webSocketFrame) throws
        Exception {
        if(webSocketFrame instanceof TextWebSocketFrame) {
            // String message = textWebSocketFrame.content().toString(Charset.forName("utf-8"));
            String message = ((TextWebSocketFrame) webSocketFrame).text();
            LOG.info("客户端接收到消息:" + message);
        }
        else {
            LOG.info("接收到消息类型" + (webSocketFrame.getClass().getName()));
        }

        SendMsg.sendPong(channelHandlerContext.channel());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        LOG.error("消息处理失败: " + cause.getMessage(), cause);
        ctx.close();
    }

    /**
     * Channel 已经被创建,但还未注册到EventLoop
     * 连接断开
     */
    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        LOG.info("连接断开 channelUnregistered SUCCESS. | name = " +channel.id().asShortText());
        super.channelUnregistered(ctx);
        channelPromise = null;
    }

    public SocketClient getSocketClient() {
        return socketClient;
    }

    public void setSocketClient(SocketClient socketClient) {
        this.socketClient = socketClient;
    }

    public ChannelPromise getChannelPromise() {
        return channelPromise;
    }
}


心跳任务类


import com.qiuhuanhen.springroot.interfaces.websocket.websocketclient.SocketClient;
import com.qiuhuanhen.springroot.interfaces.websocket.websocketclient.websocket.SendMsg;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.TimerTask;

/**
 * HeartBeatTimerTask
 *
 * @date 2019/9/2 16:24
 */
public class HeartBeatTimerTask extends TimerTask {
    private static final Logger LOG = LoggerFactory.getLogger(ReconnectTimerTask.class);
    private SocketClient socketClient;

    public HeartBeatTimerTask(SocketClient socketClient) {
        this.socketClient = socketClient;
    }

    @Override
    public void run() {
        if(socketClient != null && socketClient.isValid()) {
            SendMsg.send(socketClient.getChannel(), "客户端心跳消息 => " + System.currentTimeMillis());
        }
    }
}


重连任务类

import com.qiuhuanhen.springroot.interfaces.websocket.websocketclient.SocketClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.TimerTask;

/**
 * ReconnectTimerTask
 *
 * @date 2019/9/2 16:03
 */
public class ReconnectTimerTask extends TimerTask {
    private static final Logger LOG = LoggerFactory.getLogger(ReconnectTimerTask.class);
    private SocketClient socketClient;

    public ReconnectTimerTask(SocketClient socketClient) {
        this.socketClient = socketClient;
    }

    @Override
    public void run() {
        if(socketClient != null && !socketClient.isValid()) {
            LOG.info("=== 客户端重连 " + System.currentTimeMillis());
            socketClient.connect();
        }
    }
}

自定义线程工厂类,主要是给线程重命名 便于维护、调试

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

public class NamedThreadFactory implements ThreadFactory {
    static final AtomicInteger poolNumber = new AtomicInteger(1);
    final AtomicInteger threadNumber = new AtomicInteger(1);
    final ThreadGroup group;
    final String prefix;
    final boolean isDaemon;
    final int priority;

    public NamedThreadFactory() {
        this("pool");
    }

    public NamedThreadFactory(String prefix) {
        this(prefix, false, Thread.NORM_PRIORITY);
    }

    public NamedThreadFactory(String prefix, boolean isDaemon, int priority) {
        SecurityManager sm = System.getSecurityManager();
        this.group = (sm != null) ? sm.getThreadGroup() : Thread.currentThread().getThreadGroup();
        this.prefix = prefix + "-" + poolNumber.getAndIncrement() + "-thread-";
        this.isDaemon = isDaemon;
        this.priority = priority;
    }

    public Thread newThread(Runnable r) {
        Thread thread = new Thread(group, r, prefix + threadNumber.getAndIncrement(), 0);
        thread.setDaemon(isDaemon);
        thread.setPriority(priority);
        return thread;
    }
}

消息监听类,主要用于发送消息(包括心跳包)是否成功


import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

class CustomerChannelFutureListener implements ChannelFutureListener {
    private static final Logger LOG = LoggerFactory.getLogger(CustomerChannelFutureListener.class);

        public void operationComplete(ChannelFuture channelFuture) throws Exception {
            // LOG.info(JSON.toJSONString(channelFuture));
            if(channelFuture.isDone() && channelFuture.isSuccess()){
               // LOG.info("send success.");
            }
            else {
                channelFuture.channel().close();
                LOG.info("send error. cause = " + channelFuture.cause());
                channelFuture.cause().printStackTrace();
            }
        }
    }

简单封装的消息发送类


import com.alibaba.fastjson.JSON;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * SendMsg
 *
 * @date 2019/8/30 18:02
 */
public class SendMsg {
    private static final Logger LOG = LoggerFactory.getLogger(SendMsg.class);
    public static ConcurrentHashMap<String, Channel> ALL_CHANNEL = new ConcurrentHashMap<String, Channel>();

    public static void startSendMsg() {
        Thread thread = new Thread(new Runnable() {
            public void run() {
                while(true) {
                    sendMsgTest();
                }
            }
        });

        thread.start();
    }

    public static void sendMsgTest() {
        try {
            Map<String, Channel> map = Collections.unmodifiableMap(ALL_CHANNEL);
            LOG.info("map size = " + map.size());
            if(MapUtils.isEmpty(map)) {
                Thread.sleep(2000);
                return;
            }

            for(Map.Entry<String, Channel> entry : map.entrySet()) {
                LOG.info("------------- key = " + entry.getKey());
                send(entry.getValue(), "服务端发送消息 " + entry.getKey() + " | " + System.currentTimeMillis());
            }

            Thread.sleep(10000);
        }
        catch(Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void put(Channel channel) {
        ALL_CHANNEL.put(channel.id().asShortText(), channel);
    }

    public static void remove(Channel channel) {
        ALL_CHANNEL.remove(channel.id().asShortText());
    }

    public static void send(Channel channel, Object msg) {
        final String textMsg = JSON.toJSONString(msg);

        if(channel != null && channel.isActive()) {
            TextWebSocketFrame frame = new TextWebSocketFrame(textMsg);
            channel.writeAndFlush(frame)
                .addListener(new CustomerChannelFutureListener());
        }
        else {
            LOG.error("消息发送失败! textMsg = " + textMsg);
        }
    }

    public static void sendPing(Channel channel) {
        if(channel != null && channel.isActive()) {
            channel.writeAndFlush(new PingWebSocketFrame())
                .addListener(new CustomerChannelFutureListener());
        }
        else {
            LOG.error("消息发送失败! ping");
        }
    }

    public static void sendPong(Channel channel) {
        if(channel != null && channel.isActive()) {
            channel.writeAndFlush(new PongWebSocketFrame())
                .addListener(new CustomerChannelFutureListener());
        }
        else {
            LOG.error("消息发送失败! pong");
        }
    }

}


channel初始化


import com.qiuhuanhen.springroot.interfaces.websocket.websocketclient.handler.WebSocketClientFrameHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketClientProtocolHandler;
import io.netty.handler.timeout.IdleStateHandler;

/**
 * ClientChannelInitializer
 *
 * @date 2019/8/31 16:05
 */
public class ClientChannelInitializer extends ChannelInitializer<SocketChannel> {
    private WebSocketClientHandshaker webSocketClientHandshaker;
    private WebSocketClientFrameHandler webSocketFrameHandler;

    public ClientChannelInitializer(WebSocketClientHandshaker webSocketClientHandshaker, WebSocketClientFrameHandler
        webSocketFrameHandler) {
        this.webSocketClientHandshaker = webSocketClientHandshaker;
        this.webSocketFrameHandler = webSocketFrameHandler;
    }

    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();

        pipeline.addLast(new HttpClientCodec());//Http协议编码解码器
        pipeline.addLast(new HttpObjectAggregator(65536));//聚合 HttpRequest
        pipeline.addLast(new IdleStateHandler(5, 10, 0));
        //会处理ping pong close消息
        pipeline.addLast(new WebSocketClientProtocolHandler(webSocketClientHandshaker,true));
        pipeline.addLast(webSocketFrameHandler);
    }
}

客户端主类 : 添加工作组 , 启动websocket client , 建立连接等

import com.qiuhuanhen.springroot.interfaces.websocket.websocketclient.handler.WebSocketClientFrameHandler;
import com.qiuhuanhen.springroot.interfaces.websocket.websocketclient.task.HeartBeatTimerTask;
import com.qiuhuanhen.springroot.interfaces.websocket.websocketclient.task.ReconnectTimerTask;
import com.qiuhuanhen.springroot.interfaces.websocket.websocketclient.thread.NamedThreadFactory;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * SocketClient
 *
 * @date 2019/8/20 17:53
 */
public class SocketClient {
    private static final Logger LOG = LoggerFactory.getLogger(SocketClient.class);

    public static String CLIENT_VERSION = "client_version";
    private static final int DEFAULT_PORT = 80;
    /**
     * 长链重连间隔时间,单位s
     */
    public static long RECONNECT_INTERVAL = 10;
    /**
     * 长链心跳时间,单位s
     */
    public static long FETCH_PERIOD = 30;

    public static String host = "127.0.0.1";
    public static int port = 8585;

    private Channel channel = null;
    private NioEventLoopGroup nioEventLoopGroup;

    public AtomicBoolean CHANNEL_IS_READY = new AtomicBoolean(false);

    private ScheduledExecutorService RECONNECT_TIMER;
    private ScheduledExecutorService HEARTBEAT_TIMER;
    static final String URL = System.getProperty("url", "ws://127.0.0.1:8585/boot/imserver/1111");
    URI uri = new URI(URL);

    static {
        // RECONNECT_TIMER = Executors.newSingleThreadScheduledExecutor();
    }


    public SocketClient(URI uri) throws URISyntaxException {
        this.uri = uri;
    }

    private void start() {
        Bootstrap boot = new Bootstrap();
        nioEventLoopGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors());

        try {
            HttpHeaders httpHeaders = new DefaultHttpHeaders();
            httpHeaders.add(CLIENT_VERSION, 1);

            WebSocketClientHandshaker webSocketClientHandshaker = WebSocketClientHandshakerFactory.newHandshaker(uri,
                WebSocketVersion.V13, null, false, httpHeaders);

            boot.group(nioEventLoopGroup)
                .option(ChannelOption.TCP_NODELAY, true)
                .channel(NioSocketChannel.class);

            WebSocketClientFrameHandler webSocketFrameHandler = new WebSocketClientFrameHandler();
            webSocketFrameHandler.setSocketClient(this);

            ClientChannelInitializer clientChannelInitializer =
                new ClientChannelInitializer(webSocketClientHandshaker, webSocketFrameHandler);

            boot.handler(new LoggingHandler(LogLevel.INFO));
            boot.handler(clientChannelInitializer);

            port = (uri.getPort() == -1) ? DEFAULT_PORT : uri.getPort();
            host = uri.getHost();
            channel = boot.connect(host, port).sync().channel();
            LOG.info("SocketClient has started. CHANNEL_IS_READY = " + CHANNEL_IS_READY.get());
            webSocketFrameHandler.getChannelPromise().sync();
            LOG.info("SocketClient has started full. CHANNEL_IS_READY = " + CHANNEL_IS_READY.get());
        }
        catch(Exception ex) {
            ex.printStackTrace();
            LOG.error("connect error. uri " + uri.toString());
        }
        finally {
            // nioEventLoopGroup.shutdownGracefully();
        }
    }

    /**
     * 客户端连接服务端
     */
    public void connect() {
        stop();
        start();
        startReconnect();
        doHeartBeat();
    }

    /**
     * 开启线程-断开重连
     */
    public void startReconnect() {
        RECONNECT_TIMER = new ScheduledThreadPoolExecutor(1,
            new NamedThreadFactory("reconnect-schedule-pool", Boolean.TRUE, Thread.NORM_PRIORITY));

        // https://www.jianshu.com/p/502f9952c09b
        RECONNECT_TIMER.scheduleAtFixedRate(new ReconnectTimerTask(this),
            RECONNECT_INTERVAL * 1000L, RECONNECT_INTERVAL * 1000L, TimeUnit.MILLISECONDS);
    }

    /**
     * 心跳
     */
    private void doHeartBeat() {
        HEARTBEAT_TIMER = new ScheduledThreadPoolExecutor(1,
            new NamedThreadFactory("heartbeat-schedule-pool", Boolean.TRUE, Thread.NORM_PRIORITY));

        // https://www.jianshu.com/p/502f9952c09b
        HEARTBEAT_TIMER.scheduleAtFixedRate(new HeartBeatTimerTask(this),
            FETCH_PERIOD * 1000L, FETCH_PERIOD * 1000L, TimeUnit.MILLISECONDS);
    }

    /**
     * 客户端停止
     */
    public void stop() {
        try {
            if(nioEventLoopGroup != null) {
                nioEventLoopGroup.shutdownGracefully();
            }

            if(channel != null) {
                channel.close();
            }

            if(RECONNECT_TIMER != null) {
                RECONNECT_TIMER.shutdown();
                RECONNECT_TIMER = null;
            }

            if(HEARTBEAT_TIMER != null) {
                HEARTBEAT_TIMER.shutdown();
                HEARTBEAT_TIMER = null;
            }
        }
        catch(Exception ex) {
            //do nothing.
        }
    }


    public boolean isValid() {
        if (channel != null && channel.isActive()) {
            return true;
        } else {
            return false;
        }
    }

    public Channel getChannel() {
        return channel;
    }

    public static void main(String[] args) {
        try {
            new SocketClient(new URI(URL)).connect();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }
}


重连成功截图:
【netty】java如何作为websocket客户端 对服务端发起请求文章来源地址https://www.toymoban.com/news/detail-450767.html

到了这里,关于【netty】java如何作为websocket客户端 对服务端发起请求的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java 构建websocket客户端,构建wss客户端,使用wss连接,并发送数据到服务器端,接收服务器端消息

    Java 构建websocket客户端,构建wss客户端,使用wss连接,并发送数据到服务器端,接收服务器端消息 回调函数处理

    2024年02月13日
    浏览(61)
  • 【Java】SpringBoot快速整合WebSocket实现客户端服务端相互推送信息

    目录 什么是webSocket? webSocket可以用来做什么? WebSocket操作类 一:测试客户端向服务端推送消息 1.启动SpringBoot项目 2.打开网站 3.进行测试消息推送 4.后端进行查看测试结果 二:测试服务端向客户端推送消息 1.接口代码 2.使用postman进行调用 3.查看测试结果         WebSocke

    2024年01月20日
    浏览(61)
  • Java:SpringBoot整合WebSocket实现服务端向客户端推送消息

    思路: 后端通过websocket向前端推送消息,前端统一使用http协议接口向后端发送数据 本文仅放一部分重要的代码,完整代码可参看github仓库 websocket 前端测试 :http://www.easyswoole.com/wstool.html 依赖 项目目录 完整依赖 配置 WebSocketServer.java 前端页面 websocket.html 前端逻辑 index.js 参

    2024年02月04日
    浏览(54)
  • 如何将本地websocket服务端从本地暴露至公网实现客户端远程连接

    1. Java 服务端demo环境 jdk1.8 框架:springboot+maven 工具IDEA 2. 在pom文件引入第三包封装的netty框架maven坐标 注意:pom文件里需注释掉springbootweb启动器,web启动器默认是tomcat服务启动,会和netty服务冲突 3. 创建服务端,以接口模式调用,方便外部调用 4. 启动服务,出现以下信息表示启动成功

    2024年04月10日
    浏览(49)
  • netty构建udp服务器以及发送报文到客户端客户端详细案例

    目录 一、基于netty创建udp服务端以及对应通道设置关键 二、发送数据 三、netty中的ChannelOption常用参数说明 1、ChannelOption.SO_BACKLOG 2、ChannelOption.SO_REUSEADDR 3、ChannelOption.SO_KEEPALIVE 4、ChannelOption.SO_SNDBUF和ChannelOption.SO_RCVBUF 5、ChannelOption.SO_LINGER 6、ChannelOption.TCP_NODELAY 以上代码中

    2024年04月09日
    浏览(79)
  • netty的TCP服务端和客户端实现

    2024年02月21日
    浏览(47)
  • netty学习(3):SpringBoot整合netty实现多个客户端与服务器通信

    创建一个SpringBoot工程,然后创建三个子模块 整体工程目录:一个server服务(netty服务器),两个client服务(netty客户端) pom文件引入netty依赖,springboot依赖 NettySpringBootApplication NettyServiceHandler SocketInitializer NettyServer NettyStartListener application.yml Client1 NettyClientHandler SocketInitializ

    2024年02月11日
    浏览(60)
  • Netty理论与实践(二) 创建http客户端 服务端

    1. 使用echo服务器模拟http 通过上一篇文章中的echo服务器程序来模拟一次HTTP请求。 接收消息的代码如下: 我们通过postman直接访问echo服务器: 请求成功,echo服务器接收到了本次HTTP请求,控制台打印内容如下: 上面的原理很容易理解,postman通过tcp建立与服务器localhost:8001的连

    2024年02月16日
    浏览(36)
  • netty-发起tcp长连接(包含客户端和服务端)

    Netty是一个高性能、异步事件驱动的NIO框架,它提供了对TCP、UDP和文件传输的支持。 Netty是对JDK自带的NIO的API进行封装,具有高并发,高性能等优点。 项目中经常用到netty实现服务器与设备的通信,先写服务端代码: 服务端处理类代码: 接下来 模拟 客户端: 客户端处理类代

    2024年02月12日
    浏览(43)
  • Netty客户端发送数据给服务器的两个通道(1)

    EventLoopGroup group = new NioEventLoopGroup();// 设置的连接group。 Bootstrap bootstrap = new Bootstrap().group(group).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000) // 超时时间。 .channel(NioSocketChannel.class).handler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new

    2024年04月14日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包