1

java | 短链接解决方案

 1 year ago
source link: https://benpaodewoniu.github.io/2023/01/27/java211/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

java | 短链接解决方案 | 犀牛的博客

姑苏城外一茅屋,万树梅花月满天

客户端建立连接,发送完一次消息就断开链接。

由于客户端连接断开,所以,服务端会收到 -1

建立十个短链接。

package com.redisc;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

public class Client {
static final Logger log = LoggerFactory.getLogger(Client.class);

public static void main(String[] args) throws IOException, InterruptedException {
for (int i = 0; i < 10; i++) {
send();
}
}

public static void send() {
NioEventLoopGroup worker = new NioEventLoopGroup();

try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.channel(NioSocketChannel.class);
bootstrap.group(worker);
bootstrap.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter() {
@Override
// 会在连接 channel 建立成功后,触发 active 事件
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ByteBuf byteBuf = ctx.alloc().buffer(16);
byteBuf.writeBytes(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17});
ctx.writeAndFlush(byteBuf);
ctx.channel().close();
}
});
}
});
ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 8000);
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
log.error("error", e);
} finally {
worker.shutdownGracefully();
}
}
}

里面加了一句

// 调整 netty 接收缓冲区 bytebuf
serverBootstrap.childOption(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(16, 16, 16));
package com.redisc;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.AdaptiveRecvByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;


@Slf4j
public class Server {

public static void main(String[] args) throws IOException {
NioEventLoopGroup boss = new NioEventLoopGroup();
NioEventLoopGroup worker = new NioEventLoopGroup();

try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.channel(NioServerSocketChannel.class);
// 调整 netty 接收缓冲区 bytebuf
serverBootstrap.childOption(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(16, 16, 16));
serverBootstrap.group(boss, worker);
serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new LoggingHandler(LogLevel.DEBUG));
}
});
ChannelFuture channelFuture = serverBootstrap.bind(8000).sync();
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
log.error("error", e);
} finally {
boss.shutdownGracefully();
worker.shutdownGracefully();
}

}
}

服务端输出 「一部分」

         +-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 |................|
+--------+-------------------------------------------------+----------------+
15:52:04.878 [nioEventLoopGroup-3-10] DEBUG io.netty.channel.DefaultChannelPipeline - Discarded inbound message PooledUnsafeDirectByteBuf(ridx: 0, widx: 16, cap: 16) that reached at the tail of the pipeline. Please check your pipeline configuration.
15:52:04.879 [nioEventLoopGroup-3-2] DEBUG io.netty.handler.logging.LoggingHandler - [id: 0x71a37eb2, L:/127.0.0.1:8000 - R:/127.0.0.1:64999] READ: 16B
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 |................|
+--------+-------------------------------------------------+----------------+
...
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 11 |. |
+--------+-------------------------------------------------+----------------+
15:52:04.879 [nioEventLoopGroup-3-7] DEBUG io.netty.handler.logging.LoggingHandler - [id: 0x5e2701f9, L:/127.0.0.1:8000 - R:/127.0.0.1:65004] READ: 1B
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 11 |. |
+--------+-------------------------------------------------+----------------+

java | 粘包 & 半包 对照看。

从服务端输出可以看出

  • 确实按照每包输出,解决了粘包问题
  • 由于设置了 netty 接收缓冲区大小
    • 存在半包问题

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK