TCP与UDP:TCP提供可靠的服务UDP提供数据报. 两者都是端点协议。路由设备不管这个也不认识这个。路由设备只认识IP协议与包。但是TCP的包被放在IP上面,所以TCP必然是IP语义的收窄。TCP将IP的包语义转化为传输者语义由此建立传输服务。
TCP及以下的各层都是向机器的语义,是硬件相关的语义。而TCP以上是用户语义,是源语义。从会话层开始全是与机器无关的语义。会话、表示、应用层全是用户协议。所以http根本不符合OSI模型因为它讲的仍然是鸟语。http顶多算个会话层协议。html才是表示层协议。分布式远程调用协议iiop也是表示层协议。真正的应用层协议只能从真正的“应用”里面去找。
从物理层向应用层是一个语义逐渐收窄的过程。应用需要被表示,表示是会话的内容而会话又需要被传输,传输是在网络上进行的所以必须是一个㒳络元素。而网络又是建立在数据链路上的。数据链路是电子设备。这样串起整个7层的。
对程序员来说,,IP层与包都是隐藏的。看不见的。IP是协议实现者的工具,是武器不是程序员的菜。考虑网络性能的话对它了解一下是可以的,但是基本上跟我们无关。Socket严格说是操作系统的东西像文件IO一样,我们用的是API。并不是真正的“Socket”。所以java的socket应该是包了三层的一个API!
我们真正写程序,最好连socket也不要用因为它没有会话层会很麻烦。除非你要的会话协议找不到否则不要在socket上直接写程序,像web服务器一样,你可以在类似http一样的协议上写东西。事情上你可以且应该在http server上做网络编程!
说一个例子。前端用FLASH做请求,多个模块都有数据请求,用一个socket。多个消息顺次发出但是响应乱序了。后发出的消息相应先到了。这样就要做消息标识。比方分模块分对象。当然也可以建个连接池,把连接官起来待需分配。然后每次请求用不一样的连接。但是这样服务端就有多个连接造成服务器瞎忙或资源占用。当然可以不在乎这个,但是会话始终是一个不能否认的需求。这块工作始终是不能逃避的。而用HTTP把它包起来的好处是,它提供了一个会话界面。使事情变得简单明了,即:会话肯定是要在“会话”上进行的。而不是在“连接”上进行的。在连接上进行的那个东西叫会话。其余的东西都是建立在会话语义上的。即使你没有明显的会话层存在,语义的层次还是在。这个叫语义分层。你放弃分层不代表你不分层。层次就在那里。一直在语义里。
注意会话是两端的事情。一方有“会话”不代表另一方也有“会话”。所以你知道协议是什么东西了。协议就是大家都知道它并遵循它。于是协议是一个绕不过的东西。于是我说不要用“裸”的socket。因为它没有会话协议。会话就会乱掉。要有条理,还得要“协议”。必须有协议。当然有些程序不需要会话因为它的单次消息lifetime很长。比如文件传输。它是以传输而不是会话为主要任务的,所以socket够了。open一个socket传过去就够了没有别的说法。
关于tcp的段与ip的分片,我认为它们都是协议内部的事情只能当作协议特性考虑不能放大了看。ip分片不会向上表现或影响它可能通过影响ip服务的特性来影响上层协议但不会直接对上层编程产生影响。tcp段也是,它也是tcp内部的事情与tcp向上提供的服务也没有格式上的关系。tcp向上提供的是一个流服务,while ip向上提供的就是一个ip服务。ip是tcp的工具,while tcp又是更上层的工具!我们应该这样来理解整个协议栈。
所以不存在什么粘包这样的事情也不存在组包这样的事情,当你在用一个tcp你就应该知道你在用的是一个流服务。而当你在用一个udp,你就是在用一个数据报服务。这是你要忘掉ip。ip不为你工作,ip为tcp工作。它是通过为tcp工作来为你工作的。向让它直接为你工作的想法不合适也不可行那只是痴心妄想,是不存在的事情。存在的是tcp为你在工作。你有的是tcp不是ip。这是正确的tcp哲学。其余都不是正道。
所以写网络程序,了解tcp的传输特性才是最重要的而不是别的事情。当然底层会对上层产生影响,但是你思考问题的思路还是要依据正确的模型。tcp根本没有包,为什么要说粘包组包这样的东西?udp的确有个"报”但那也不是“包”,比如包会被拆掉而对于报这却不可能发生。没有这样的事情。这对于理清编程思路是非常必要的。
来源:oschina
链接:https://my.oschina.net/u/109289/blog/210499