TCP的面向字节流和粘包问题

一、面向字节流

如何理解TCP是面向字节流协议

之所以说TCP是面向字节流协议,UDP是面向报文协议。主要是因为发送方的发送消息的机制不同

UDP是面向报文协议

        udp在发送消息时,在传输层直接就将一个消息打包成一个完整的包,组装好udp头部,不进行切割,就转发给网络层。也就是每一个UDP报文就是一个消息。服务端在接收到udp报文时,会将它放到一个队列中,一个元素就是一个udp报文。每次读取时,读取一个元素

TCP是面向字节流协议

        当tcp在传输层发送消息时,一个消息可能会被分割成多个tcp报文进行转发给网络层。我们不能认为一个tcp报文就是一个消息,所以tcp是面向字节流协议

由于一个消息对应的不是一个tcp报文,如果接受方不知道一个消息的长度或者分割的边界在哪里,就会无法组装成一个消息,这就形成了粘包问题

二、粘包问题解决

三种方式:

  • 固定长度的消息
  • 特殊字符当做边界
  • 自定义消息结构

固定长度的消息

将消息长度固定,比如规定一个消息长度为64字节,那么只要接收到了64字节,就认为这个内容是一个完整的消息

特殊字符作为边界

我们可以在两个消息之间加入一个特殊字符,如果读到了这个特殊字符,则认为一个消息已经完整的接收到了。
比如我们的http

HTTP通过回车换行来判断消息边界。

需要注意的是,如果消息内容中含有分割消息的特殊字符的话,需要进行转义处理,否则则会错误判断消息边界

自定义消息结构

我们可以自定义消息结构,由包头和数据来构成,包头里有一个字段表示紧随其后的一个消息有多大。

当接收方接收到包头时,就会解析包头里的数据长度,接下来就读取数据,知道读取到指定长度时,就是一个完整的消息

        TCP是一种面向字节流的协议,它将数据视为连续的字节流,而不是分割成消息。这意味着在发送端,应用程序将数据写入TCP连接时,TCP会将数据转换为字节流,并在接收端将字节流重新转换回数据。

        面向字节流的特性使得TCP非常灵活,可以传输任意类型的数据,包括文本、图像、音频等。然而,正是由于面向字节流的特性,导致了粘包问题的出现。

下面是一个简单的Java代码示例,演示了粘包问题的可能场景:

import java.io.*;
import java.net.*;

public class TCPServer {
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(8888);
        Socket socket = serverSocket.accept();

        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);

        String inputLine;
        while ((inputLine = in.readLine()) != null) {
            System.out.println("Received message: " + inputLine);
        }

        socket.close();
        serverSocket.close();
    }
}
import java.io.*;
import java.net.*;

public class TCPClient {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("localhost", 8888);
        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);

        out.println("Message 1");
        out.println("Message 2");
        out.println("Message 3");

        socket.close();
    }
}

        在这个示例中,客户端连续发送了三条消息给服务器端,但由于TCP的面向字节流特性,这三条消息可能会被合并成一个数据包发送给服务器端,从而造成粘包问题。

三、解决方法

        解决粘包问题的方法有多种,常用的方法包括消息边界标记、消息长度标记和使用消息头等。其中,消息边界标记是一种常见且简单的解决方法,即在每条消息的末尾添加特定的分隔符,如换行符(\n),接收端根据分隔符来识别消息的边界。

下面是一个使用消息边界标记解决粘包问题的Java代码示例:

import java.io.*;
import java.net.*;

public class TCPClient {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("localhost", 8888);
        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);

        out.println("Message 1\n");
        out.println("Message 2\n");
        out.println("Message 3\n");

        socket.close();
    }
}

        在这个示例中,客户端在每条消息的末尾添加了换行符(\n),接收端可以根据换行符来识别消息的边界,从而正确解析数据,避免了粘包问题的出现。

  • 22
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TCP协议是一种面向连接的可靠传输协议,它将数据分成一个一个的数据进行传输。但是,由于网络传输的不确定性,TCP和分问题就会出现。 1. TCP问题 TCP问题是指发送方将多个数据合并成一个数据发送,接收方无法区分多个数据的边界,从而无法正确处理数据。造成TCP问题的原因有多种,比如发送方发送的数据过大、发送速度过快、网络延迟等。 解决方法: (1) 设置消息边界标识符 在发送的消息中添加一个特殊的标识符,如换行符、空格等,用来标识消息的边界。接收方根据标识符来判断消息的边界,将消息分隔成多个数据。 (2) 定长消息 可以设置一个固定长度的消息,每次发送的数据都是定长的。这样接收方就可以根据固定长度来将消息分隔成多个数据。 2. TCP问题 TCP问题是指发送方将一个数据分成多个数据发送,接收方接收后需要将多个数据组合成一个完整的数据,才能进行处理。造成TCP问题的原因有多种,比如发送方发送的数据过大、网络拥塞等。 解决方法: (1) 设置消息长度 在消息中添加消息长度信息,接收方接收到数据后,根据长度信息将多个数据组合成一个完整的数据。 (2) 固定长度消息 发送方每次发送的数据都是固定长度的,接收方根据固定长度来将多个数据组合成一个完整的数据。 总之,TCP和分问题可以通过合理的协议设计和网络优化来解决。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值