鍍金池/ 問答/Java  Linux  網(wǎng)絡(luò)安全/ netty拆包、粘包的問題:服務(wù)端接收tcp請(qǐng)求的時(shí)候,為什么需要數(shù)據(jù)拼裝?或者

netty拆包、粘包的問題:服務(wù)端接收tcp請(qǐng)求的時(shí)候,為什么需要數(shù)據(jù)拼裝?或者是接收什么樣的數(shù)據(jù)需要數(shù)據(jù)拼裝?

netty官網(wǎng)的user-guide里的demo,有一個(gè)小節(jié)的內(nèi)容弄的不是特別明白。
原文:netty4.x用戶指南
中文:netty4.x用戶指南
文章里說的,客戶端發(fā)過來的數(shù)據(jù)包,服務(wù)端是以流的形式接收的,因此需要有一個(gè)處理邏輯,來將接收到的流解析成客戶端發(fā)送來的真正的一個(gè)個(gè)的數(shù)據(jù)包。

但是我在自己的demo里,感覺不到這樣做的必要額?因?yàn)榭蛻舳嗣堪l(fā)過來一段字符串,服務(wù)端都能通過

String recMsg = byteBuf.toString(CharsetUtil.UTF_8);

完整地解析出來,并沒覺得有必要進(jìn)行文中所說的操作。

@Slf4j
public class EchoHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ByteBuf buf = (ByteBuf) msg;
        String msgStr = buf.toString(CharsetUtil.UTF_8);
        log.info("receive message: {}", msgStr);
        
        ChannelFuture f = ctx.write(buf);
        f.addListener(new ChannelFutureListener() {
            
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                assert f == future;
                ctx.close();
            }
        });
    }
}

是我哪里理解的有偏差嗎?
比如說,客戶端寫過來的數(shù)據(jù)并不只有字符串,里面還夾雜著其他類型的數(shù)據(jù)比如一個(gè)long類型?

ByteBuf time = ctx.alloc().buffer(4); // ChannelHandlerContext ctx
String dateNow = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
long curTime = System.currentTimeMillis();
time.writeBytes(dateNow.getBytes());
time.writeLong(curTime);
ctx.writeAndFlush(time);

如果客戶端像這一行寫數(shù)據(jù),服務(wù)器單一按照string類型來解析的話,的確是會(huì)亂碼。
但現(xiàn)實(shí)真的會(huì)有這種情況存在嗎?有大佬給兩個(gè)具體一點(diǎn)的例子么?

回答
編輯回答
淚染裳

其實(shí)這就是一個(gè)典型的粘包、拆包的問題。

導(dǎo)致的原因就是因?yàn)?TCP 是流式的,就像水流一樣沒法知道一段完整的報(bào)文到哪里是截止的。

報(bào)文越長就越可能出現(xiàn)這樣的問題。

文中提到的其實(shí)是按照字節(jié)長度來防止拆包,常見的還有通過分隔符,比如知道讀取到指定的分隔符才算做是獲取到了完整的報(bào)文。

這些其實(shí) Netty 都是有內(nèi)置的處理器。

2017年11月5日 00:36