This is the 25th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

Glue bag phenomenon

As an example of what sticky packets are, here is a client code that simply sends a string of 0 to 15 (decimal bytes 00 to 0f) to the server ten times:

public class StudyClient {
    static final Logger log = LoggerFactory.getLogger(StudyClient.class);
    public static void main(String[] args) {
        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 ch) throws Exception {
                    log.debug("connected...");
                    ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                        @Override
                        public void channelActive(ChannelHandlerContext ctx) throws Exception {
                            log.debug("sending...");
                            // Send 16 bytes of data each time, a total of 10 times
                            for (int i = 0; i < 10; i++) {
                                ByteBuf buffer = ctx.alloc().buffer();
                                buffer.writeBytes(new byte[] {0.1.2.3.4.5.6.7.8.9.10.11.12.13.14.15}); ctx.writeAndFlush(buffer); }}}); }}); ChannelFuture channelFuture = bootstrap.connect("127.0.0.1".8080).sync();
            channelFuture.channel().closeFuture().sync();

        } catch (InterruptedException e) {
            log.error("client error", e);
        } finally{ worker.shutdownGracefully(); }}}Copy the code

The server should normally receive ten messages, each of which is 0 to 15 (00 to 0F), but in reality the result is the following:

It can be seen that although the client sends data to the server 10 times through channel in 16 bytes, butThe server receives only one packet, and the size of the received data is 160B, that is, the total size of the data sent by the client. This is the sticky packet phenomenon

Phenomenon of half a pack

Adjust the channel capacity between client and server:

Serverbootstrap. option(channeloption.so_rcvbuf, 10); serverbootstrap. option(channeloption.so_rcvbuf, 10);Copy the code

Pay attention to

Serverbootstrap. option(channeloption.so_rcvbuf, 10) Affects the size of the underlying receive buffer (that is, the sliding window), which only determines the minimum unit of read by Netty. Netty usually reads an integer multiple of it each time

The result at this time is:

See the data sent by the client each time,The sent data cannot be received at a time because the channel capacity is insufficient. Procedure, then produced the half-pack phenomenon

The phenomenon of analysis

Stick package

  • The phenomenon of
    • Send ABC and def, and receive abcdef
  • why
    • The application layer
      • The receiver ByteBuf setting is too large (Netty default 1024)
    • Transport layer – Network layer
      • Sliding window: Assume that the sender 256 bytes represents a complete packet. However, the 256 bytes are cached in the sliding window of the receiver because the receiver does not process the packet in time and the window size is large enough (larger than 256 bytes). If multiple packets are cached in the sliding window, the packet will be stuck
      • Nagle algorithm (if less data is sent at one time, it waits for other data to be sent) : sticky packets

Half a pack

  • The phenomenon of
    • Send abcdef and receive ABC and def
  • why
    • The application layer
      • The value of ByteBuf on the receiving end is smaller than the actual amount of data sent
    • Transport layer – Network layer
      • Sliding window: Assume that the window of the receiver is only 128 bytes and the size of the packet of the sender is 256 bytes. In this case, the window of the receiver cannot contain all the packets of the sender. The sender can only send the first 128 bytes and wait for ack before sending the rest, resulting in half packets
    • Data link layer
      • MSS limit (maximum length that can be sent at one time) : When the sent data exceeds the MSS limit, the data will be split and sent, resulting in half packets

nature

The essence of sticky packets and half packets occurs because TCP is a streaming protocol and messages have no boundaries