文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/
1.背景
在上一篇博客中我详细介绍了809协议的内容。809协议规范了通信的报文,通信的规则等,但是并没限制通信使用的传输协议。这里,我将分别介绍利用TCP和UDP传输协议来实现的809协议对接的方法。
2.TCP和UDP的介绍
TCP协议和UDP协议均是面向传输层的一种协议。而我们常说的HTTP协议则是面向应用层的一种协议。
我们常说的TCP/IP协议,则是一个协议簇,其中TCP、UDP协议均包含于这个协议簇。至于这个协议为什么叫TCP/IP,是因为TCP和IP协议是其中最重要的两个协议。
2.1TCP协议介绍
TCP(Transmission Control Protocol,传输控制协议)是面向连接的协议,也就是说,在收发数据前,必须和对方建立可靠的连接。一个TCP连接必须要经过三次“对话”才能建立起来,其中的过程非常复杂,只简单的描述下这三次对话的简单过程:主机A向主机B发出连接请求数据包:“我想给你发数据,可以吗?”,这是第一次对话;主机B向主机A发送同意连接和要求同步(同步就是两台主机一个在发送,一个在接收,协调工作)的数据包:“可以,你什么时候发?”,这是第二次对话;主机A再发出一个数据包确认主机B的要求同步:“我现在就发,你接着吧!”,这是第三次对话。三次“对话”的目的是使数据包的发送和接收同步,经过三次“对话”之后,主机A才向主机B正式发送数据。
总结上面这段话,主要包含了两个关键词:三次握手、可靠连接:
如建立连接一般复杂,TCP协议断开也相对复杂,需要进行四次挥手:
2.2UDP协议介绍
UDP(User Data Protocol),即用户数据报协议,其包含的特征主要如下:
a.UDP是一个非连接的协议,传输数据之前,源端和终端不建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制;在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。
b.由于传输数据不建立连接,因此也就不需要维护连接状态,包括收发状态等,因此一台服务机可同时向多个客户机传输相同的消息。
c.UDP信息包的标题很短,只有8个字节,相对于TCP的20个字节信息包的额外开销很小。
d.吞吐量不受拥挤控制算法的调节,只受应用软件生成数据的速率、传输带宽、源端和终端主机性能的限制。
e.UDP使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的链接状态表(这里面有许多参数)。
f.UDP是面向报文的。发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付给IP层。既不拆分,也不合并,而是保留这些报文的边界,因此,应用程序需要选择合适的报文大小。
我们经常使用“ping”命令来测试两台主机之间TCP/IP通信是否正常,其实“ping”命令的原理就是向对方主机发送UDP数据包,然后对方主机确认收到数据包,如果数据包是否到达的消息及时反馈回来,那么网络就是通的。
总结UDP协议,其最大的特点是其无连接性,支持广播通信(支持一对多、多对多通信)。广播地址(Broadcast Address)是专门用于同时向网络中所有工作站进行发送的一个地址。在使用TCP/IP 协议的网络中,主机标识段host ID 为全1 的IP 地址为广播地址,广播的分组传送给host ID段所涉及的所有计算机。例如,对于10.1.1.0 (255.255.255.0 )网段,其广播地址为10.1.1.255 (255 即为2 进制的11111111 ),当发出一个目的地址为10.1.1.255 的分组(封包)时,它将被分发给该网段上的所有计算机。
2.3协议对比
TCP与UDP区别总结:
a.TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接。
b.TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付 。
c.TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的
UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)。
d.每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信 。
e.TCP首部开销20字节;UDP的首部开销小,只有8个字节。
f.TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道。
3.Socket编程
3.1基本概念
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。
建立网络通信连接至少要一对端口号(socket)。socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力。
目前各大主流语言基本都支持socket编程。C#基于socket封装了TCPClient以及UDPClient类,使得socket编程更加简单。
在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式:
同步:所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。也就是必须一件一件事做,等前一件做完了才能做下一件事。例如普通B/S模式(同步):提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事。
异步:异步的概念和同步相对。当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。 例如 ajax请求(异步): 请求通过事件触发->服务器处理(这是浏览器仍然可以作其他事情)->处理完毕。
阻塞:阻塞调用是指调用结果返回之前,当前线程会被挂起(线程进入非可执行状态,在这个状态下,cpu不会给线程分配时间片,即线程暂停运行)。函数只有在得到结果之后才会返回。有人也许会把阻塞调用和同步调用等同起来,实际上他是不同的。对于同步调用来说,很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回而已。 例如,我们在socket中调用recv函数,如果缓冲区中没有数据,这个函数就会一直等待,直到有数据才返回。而此时,当前线程还会继续处理各种各样的消息。
非阻塞:非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。
对象的阻塞模式和阻塞函数调用:
对象是否处于阻塞模式和函数是不是阻塞调用有很强的相关性,但是并不是一一对应的。阻塞对象上可以有非阻塞的调用方式,我们可以通过一定的API去轮询状 态,在适当的时候调用阻塞函数,就可以避免阻塞。而对于非阻塞对象,调用特殊的函数也可以进入阻塞调用。函数select就是这样的一个例子。
总结为:
a.同步,就是我调用一个功能,该功能没有结束前,我死等结果。
b.异步,就是我调用一个功能,不需要知道该功能结果,该功能有结果后通知我(回调通知)。
c.阻塞,就是调用我(函数),我(函数)没有接收完数据或者没有得到结果之前,我不会返回。
d.非阻塞,就是调用我(函数),我(函数)立即返回,通过select通知调用者。
3.2同步和异步的实现
3.2.1阻塞通信
3.2.2非阻塞通信
实现非阻塞通信有两种方式,一种是利用异步方式,另一种使用多线程方式实现。两者的原理也是各不相同:
a.线程本质上是进程中一段并发运行的代码,所以线程需要操作系统投入CPU资源来运行和调度;
b.异步本质上是计算机硬件功能,其操作无须消耗CPU时间的I/O操作;
编写异步操作的复杂程度较高,程序主要使用回调方式进行处理,处理函数可以不必使用共享变量;
c.多线程是顺序执行,编程简单。但是线程的使用(滥用)会给系统带来上下文切换的额外负担。并且线程间的共享变量可能造成死锁的出现。
当需要执行I/O操作时,使用异步操作比使用线程+同步 I/O操作更合适。I/O操作不仅包括了直接的文件、网络的读写,还包括数据库操作、Web Service、HttpRequest以及.net Remoting 等跨进程的调用。
线程适用那种需要长时间CPU运算的场合,例如耗时较长的图形处理和算法执行。
3.2.2.1多线程实现
3.2.2.2异步实现
4.809协议对接的实现
4.1TCP协议对接(部分)
由于TCP是长连接,所以这里需要用非阻塞方式通信,选择多线程方法解决:
4.2UDP协议对接(部分)
UDP不需保持连接状态,所以监听端口完成操作即可,由于接受消息后操作基本不耗时,所以没有启用多线程:
4.3对809协议解析的实现(部分)
5.总结
在研究生期间时,研究过一段时间的socket通信。当时对P2P模式,以及UDP打洞都还挺感兴趣。以后有机会和大家在一起探讨。
-----欢迎转载,但保留版权,请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/
如果您觉得本文确实帮助了您,可以微信扫一扫,进行小额的打赏和鼓励,谢谢 ^_^