TCP/IP协议学习笔记(一)

之前只是简单使用过C#Socket类做过一些非常简单的编程,但是对于网络编程,实际还是完全的新手,虽然理解一些概念,可是具体怎么去做却还是一头雾水。写这些笔记,只是为了记录自己的学习过程,并把头脑里面那些碎片化的知识做一个整理。

TCP/IP协议的底层原理,理解的还不太清晰,这里就只记录一下TCP/IP协议中常见的一个基本问题吧。

一、TCP协议的基本概念

1、传输层协议:在分层模型(一般是四层: 网络接口层(也可以叫数据链路层)、网络层、传输层、应用层)中,TCP协议属于传输层,负责应用层与网络层之间的数据传输,另一个常见的传输层协议UDP协议。
注:这里有一个知识上的不明确,TCP/IP协议是否就是TCP协议 IP协议的组合??
2、数据传输方式:TCP协议采用的是流传输,传输的信息单位被成为报文段。所以通过TCP协议,数据是以连续字节流的形式从一端传入另一端。与之对应的UDP协议采用的是数据包传递
(对流传输的理解,可以将数据流看作水流,整个数据传输的过程中,一个数据报文段中间不会有任何中断,而一个数据报文段也没有固定的长度,一组数据既可以在一个流中传递,也可以被截断成多个流;相反,数据包是有固定长度的(每一个包长度可以不同),可以理解为数据包具有“消息保护边界”)
这里可以参考:http://blog.csdn.net/zhangxinrun/article/details/6721427

二、粘包问题:

(1)发送端: TCP的流传输过程中,为了节省开销,减少发送次数,当流的缓存区达到一定值后才会发送。这样一个流中的数据可能就不会刚好是一个数据包。
(2)接收端: 当数据流传输到的时候,数据会先放入数据缓存区。而 接收程序,有时候由于一些原因,并不能马上取走缓存区的数据,导致数据缓存区中的数据也可能不会刚好是一个数据包。
(3)传输过程:由于存在一定的延时,数据接收顺序并不一定与发送顺序相同,TCP协议采用了一些办法(如数据包编号)可以标识先后,在收到数据之后可以将数据有序排列在缓存区,而这也可能会导致数据缓存区中的数据并非一个数据包。
 这样的情况就被称为粘包。
1、粘包的几种情况,举个简单的例子,先发了A包,在发B包
(1)一个报文段 刚好就是A全部的内容;
(2)A的全部内容 + B的一部分内容;
(3)A的全部内容+B的全部内容;
(4)A的一部分内容(A太大)
P.S:TCP协议会有一些办法将接收数据排好序,所以不需要考虑顺序问题(TCP协议具体是如何实现这一点的?)
2、粘包问题的解决

传输层协议本身并不关系数据内容,数据内容完全交由应用层解析。而字节流数据,是连续的,非结构化的,粘包现象的出现便是这个特性的体现。所以为了得到易于解析的非连续,结构化的数据。我们需要采取一定的规则,对数据进行封包,以方便应用层解析与识别。

封包的一般规则

数据包
{
      包头;//包头,必须定义为固定长度的数据,可能包含的内容包括,(1)数据包类型,用于标识如何数据包(比如是什么类型,或者调用什么方法)(2)数据包长度,用于指示该包的长度;(3)包头标识(4)协议类型   (3)、(4)都不是必须的。
      包体;//包体 包含的就是所有要传输的数据内容(可以是类型、方法标识等)
}


拆包

因为包头是固定长度的数据,一般也比较短,所以先取出包头长度的数据,然后进行解析,读出包长和类型(OP操作码)

(注:一个问题,如果数据长度小于一个包头长度怎么办?)

对于上面粘包的4种情况,这里假设n为包长,m为设置的接收缓存区的长度

(1)n = m ; 直接读取数据,清空缓存区,——》等待下一次接收

(2)n

  (3)   n>m;  将m长度的数据移入缓存区——》等待下一次接收——》将新收到的数据与缓存区的数据重组——》回到开始的判断




你可能感兴趣的:(学习笔记)