从TCP聊起
作为一个程序员,假设我们需要在A电脑的进程发一段数据到B电脑的进程,我们一般会在代码里使用socket进行编程。
这时候,我们可选项一般也就TCP和UDP二选一。TCP可靠,UDP不可靠。除非是马总这种神级程序员(早期QQ大量使用UDP),否则,只要稍微对可靠性有些要求,普通人一般无脑选TCP就对了。
类似下面这样。
fd = socket(AF_INET,SOCK_STREAM,0);
其中SOCK_STREAM,是指使用字节流传输数据,说白了就是TCP协议。
在定义了socket之后,我们就可以愉快的对这个socket进行操作,比如用bind()绑定IP端口,用connect()发起建连。
握手建立连接流程
在连接建立之后,我们就可以使用send()发送数据,recv()接收数据。
光这样一个纯裸的TCP连接,就可以做到收发数据了,那是不是就够了?
不行,这么用会有问题。
使用纯裸TCP会有什么问题
八股文常背,TCP是有三个特点,面向连接、可靠、基于字节流。
TCP是什么
这三个特点真的概括的非常精辟,这个八股文我们没白背。
每个特点展开都能聊一篇文章,而今天我们需要关注的是基于字节流这一点。
字节流可以理解为一个双向的通道里流淌的数据,这个数据其实就是我们常说的二进制数据,简单来说就是一大堆 01 串。纯裸TCP收发的这些 01 串之间是没有任何边界的,你根本不知道到哪个地方才算一条完整消息。
01二进制字节流
正因为这个没有任何边界的特点,所以当我们选择使用TCP发送"夏洛"和"特烦恼"的时候,接收端收到的就是"夏洛特烦恼",这时候接收端没发区分你是想要表达"夏洛"+"特烦恼"还是"夏洛特"+"烦恼"。
消息对比
这就是所谓的粘包问题,之前也写过一篇专门的文章聊过这个问题。
说这个的目的是