精华内容
参与话题
问答
  • 本文转自... 很早就计划写篇关于UDP的文章,尽管UDP协议远没TCP协议那么庞大、复杂,但是,要想将UDP描述清楚,用好UDP却要比TCP难不少,于是文章从下笔写,到最终写成,...
    展开全文
  • 如果你真的精通TCP行为,那么本文不读也罢,直接发邮件给我,我们切磋一下,如果只是了解socket接口,那么建议读本文,然后一定再看一下《TCP协议疑难杂症全景解析》0.UDP协议和TCP协议 UDP是用户数据报协议...
    如今,但凡说精通网络的,第二个意思就是“精通TCP”,事实上,很多自称精通TCP的家伙们只是精通socket接口而已,对TCP行为精通的并不多,笔者也不算精通,但绝对是中等以上水平。如果你真的精通TCP行为,那么本文不读也罢,直接发邮件给我,我们切磋一下,如果只是了解socket接口,那么建议读本文,然后一定再看一下《TCP协议疑难杂症全景解析

    0.UDP协议和TCP协议

    UDP是用户数据报协议的简称,对于分组交换网络,它实际上扮演了传统邮局的角色,而TCP则是扮演了电话运营商以及物流公司的角色,对于分组交换网络而言,UDP要比TCP更加基本一些,可以说,TCP则是实现一种基于流的通信过程,在IP这个数据报协议之上,TCP和UDP分别实现了更高层的“电路交换”和“分组交换”。

    1.带连接的udp(connect udp)

    很多人都以为UDP连接不连接无所谓,实则不是这么简单,但凡技术上的事,没有无所谓,除非你能给出比让你无所谓多一倍的理由。

    1.1.效率

    在操作TCP/IP协议的时候,说白了就是编写基于网络通信代码的时候,你必须知道你所使用的协议是在哪里实现的,对于大多数的操作系统,协议栈都是内核的一部分,因此它们是在内核空间运行的,这就涉及到一个会影响效率的问题,那就是内核空间和用户空间的切换过程你要了解,对于x86处理器以及大多数其它处理器,这个切换是比较耗时的,涉及到上下文的save/restore,因此如果你的应用是效率优先的,那么就要想办法最小化切换次数,这还不够,还有就是如果切换避免不了,那么就尽量减少拷贝次数,由于UDP是基于数据报的,数据只要准备好就会调用一次send或者sendto,这个是由应用逻辑决定的,然而我们可以决定的是到底是用send还是sendto,看看参数便知,sendto的参数要比send更多,因此这就意味着,如果使用sendto,需要拷贝的参数就会多一些,参数到了内核空间之后,内核还要准备数据结构暂时容纳这些参数,当数据发出之后,内核需要释放这些暂时存储的参数(当然可以使用栈来管理这些参数以实现自动释放)。
    如果一个UDP是connect的,那就可以在connect之后直接调用send了,内核在应用connect之后就永久维护了这次UDP的连接,以后每次收发数据,内核不再需要分配/删除这些数据,而只是查找就可以了,同时也减少了数据的拷贝量,既然connect的UDP在内核中已经存在了一个“连接”,那么无论何时,只要通信没有结束,内核总是能随时追踪到这个“连接”,因此就引出了1.2。

    1.2.错误提示

    如果是一个没有“连接”的UDP,数据在调用sendto发出后发送端就释放了关于目的地的任何信息,然而数据如果最终由IP封装(或者被任何有错误提示的下层协议封装),数据在半路上或者终点遇到某种问题不能到达目的地时,会有ICMP(对于非IP协议,可以是其它机制)错误信息返回,然则发送端已经不再可能知道该错误信息要发给哪个应用(源/目的地信息已经释放)。
    对于有“连接”的UDP通信,由于内核协议栈已经维护了从源到目的地的单向连接,因此当错误信息发来的时候,内核协议栈会准确定位到该转发给哪个应用。
    最后说明一点,UDP的连接是单向的,在调用connect的时候并不会产生任何通信流量,它只是在内核协议栈中绑定了一对五元组而已,该五元组是:UDP协议/源IP/源端口/目的IP/目的端口。

    2.udp高效率的神话

    如果你在网上询问,TCP和UDP的区别,得到的结果无非以下几种:UDP不需要处理确认,UDP比较高效,基于连接与无连接,TCP耗资源,...
    然而以上这些都是神话,是神话就是要破除它。UDP并不是一定比TCP高效,要知道,TCP发展到今天,其算法已经非常丰富,合理配置的话足以应付各种复杂的环境,大多数情况下都会比UDP更加高效。

    3.udp的设计-多路复用的IP

    TCP/IP只是一个协议族,在这个协议族上,完成了所有应该完成的工作,UDP作为一种数据报协议,其更多的作用在于使用端口的概念进行应用复用,在实现上,它基本上是复制了IP协议,在复制的基础上,增加了一个可选的校验和,一定程度上保护了数据的完整性,当然你也可以不要它。
    IP协议完美的实现了数据报业务,发后不管结果,尽力而为-虽然ICMP一定程度提供了有限的反馈信息。有人说IP协议很不负责,然则分层模型的要旨就是每层仅提供单一的服务,这也是unix的哲学。IP协议仅仅提供了最底层的数据报分组交换通信,这是和电路交换完全并行的一个通信模型。有的时候,真的需要这样的“发后不管,尽力而为”的服务,TCP/IP的绝妙解决方式不是直接让IP来提供这个服务,而是在IP之上提供了多路复用的UDP,结果是,针对于主机,同一个IP可以承载多个“发后不管,尽力而为”的服务,IP最终仅仅提供传输服务。

    4.udp的使用场合前奏

    读懂了第3节,那么我们接着往后说,到底哪些业务需要“发后不管,尽力而为”的服务呢?在现实中,我们知道,平信是这样的业务,说起平信,值得还念,90后的几乎再也不需要写信了,当时我上大学时,一周要给远方的女朋友寄送最少一封信,可是有时候信件一周内就到了,可是有时,信件丢了,因此我要花费大量的电话时间和金钱来解释以证明自己真的写了信,只是没有送到而已,也有的时候,当我解释了之后,信件莫名其妙的到了,延迟了好久。这就是发后不管,尽力而为的服务,也有那么一次,为了澄清一个事实-这封信绝对不能丢,我使用了特快专递,虽然并没有表现出什么特快,然而我收到了回执,这就不是发后不管的服务,而是“带确认的服务”,因此是否发后不管和通信效率并没有什么必然关联,这是需要澄清的。
    很多人都认为udp应用在实时要求比较高的领域,然后还说什么自己完成顺序和重传,既然需要保序和重传,那为何不直接使用TCP呢,这些人实际上知道TCP之所以效率低,就是因为它需要处理按序交付以及处理重传。如果为UDP加上了这些功能,那岂不是UDP的优势也不再了?
    我想,上述这些人一定是教科书读太多了,加上各种教科书又都是从那么几本经典书籍以及不多的几篇RFC中摘录的,因此“天下教科书一大抄”本身成就了众口铄金的效果。实际情况远非这么简单。TCP真的没有UDP效率高吗?未必!
    要知道,我们网民生活的互联网的每一根通信管道并不是固定容量的,而是可以伸缩的,然而标准的UDP在发送时却是每包长度固定的,为了简单起见,使用UDP协议的应用程序之间都使用固定长度的包通信,这就有问题了...

    4.1.问题一:无法利用空闲带宽导致资源浪费

    很简单的一个场景,UDP双方每次以512字节定长包通信,这就意味着发送端发出512字节,接收端就接收512字节,每512字节封装一个IP包,除了端口复用这个优势之外,白白增加了一个UDP头的封装成本。即使能一次发送更多的数据,也不得不每512字节发一次,对于使用TCP的应用,数据到达内核协议栈以后,某些情况下,可以暂时积攒起来,这样就节省了封装的费用,但是并不会浪费时间导致交互问题,因为TCP会使用一种很聪明的算法,当发现数据必须积攒的时候,就说明此时不积攒也不行,TCP的复杂算法会在延迟和吞吐量之间达到一个很好的平衡,详见《TCP协议疑难杂症全景解析
    最简单的一个事实就是链路的MTU几乎不会影响到UDP,而会影响到TCP,而这直接影响IP的分片,这又是一个效率问题,极端点说,UDP可能每次发送的包是MTU的几百分之一,也可能是MTU的几百倍,前者太低效,后者将消耗转嫁给了IP。

    4.2.问题二:网络拥塞或两端性能不匹配时无法被反馈导致大量丢包

    对于TCP而言,它可以使用拥塞控制和流量控制算法智能控制该发送速率,而对于UDP,由于没有确认机制,即使网络拥堵了或者对端机器吃不消了,发送端还是不停的发送,这样就会加重病态的恶化程度,对于这种恶化,UDP的收发两端不必负任何责任,详见5.1。

    4.3.改进UDP发包为动态长度代价太高

    由于上述的两个问题,有必要对UDP在用户态做一些调整,然而因为有TCP的存在,到底是做调整还是直接用TCP,这是一个问题,该问题的最终解决涉及到时间成本和金钱成本。

    5.UDP真正的使用场合

    5.1.网络情况于公平性

    虽然udp没有流量控制和拥塞控制,也不需要确认,但是这并不一定会提高效率,俗话说,磨刀不误砍柴工,有时候一些必要的维护工作是要做的,虽然udp比tcp简洁很多,但在这简洁的背后,其高效率的假象难免会有一些掩耳盗铃的意味,一个udp数据报发出去就不管了,你收不到确认,于是你默认它已经安全到达对端了,这就好比你不希望代码出错,于是你将代码中的错误提示删除是一样的道理。
    实际上,在网络极度拥堵的情况下,udp的丢包率极其高,这正是因为它没有拥塞控制导致的,由于同样没有流量控制,在两端速率不匹配的情况下,也会出现持续不减的高丢包率,而TCP就没有这个问题,因为它会自我调节。
    再谈公平性的影响。tcp天生就是公平的,而udp不是,它是毫无秩序的,就和真正的分组交换网的定义一样。由于没有秩序,网络情况丝毫不会反馈给端点,不但自身会造成高丢包率,还会挤压tcp流量的带宽。
    用一个实例结束本节,那就是道路交通。北京交通可以看做udp,而上海交通则是tcp,虽然都面临拥堵,但是你会发现,北京的车一旦遭遇拥堵,几乎就卡死了,而上海虽然有的路段比北京还堵,然而不会卡死,车流即使再慢也仍会缓慢前行。

    5.2.通讯持续性和交互性

    对于分组交换网络通信,协议栈的成本主要表现在以下几方面:a.封装导致的空间复杂度;b.缓存导致的时间复杂度。对于封装,无疑和缓存是直接对立的,如果你想将数据马上发出去,那么就需要直接封装并发给下层,这样无疑消耗了更多的协议头空间,如果你不想如此消耗,那么就把载荷缓存,待缓存达到一定量时再一次性发出,这样“协议头/载荷”值将最小化,无疑节省了空间,但是浪费了时间。
    以上原理理解之后,紧接着你可能会想到两种通信类型,一类是短连接通信,一类是长连接通信。考虑通信效率的时候一定要考虑这种通信持续性所带来的影响,如果你只需要发一个包且该包可以发后不管且自己有重发/轮询机制,那么UDP比较好,如果此时用TCP的话,光握手就需要2个包(第三次握手可以携带数据),平均下来不划算,这样的例子就是DNS查询。反之若是长连接,那么TCP握手和挥手的额外时间会平摊到持久的通信中,在持久的通信中,应用程序可以从TCP流中得到额外的好处,比如积累发送,Nagel算法带来的好处等等,另外,大多数情况,确认并不是一种开销,因为很多TCP算法都是用捎带确认或者延迟确认,因此大多数情形下确认包就不会影响发送端的速率又不会占据带宽。
    在用户的交互体验上,UDP协议的通信完全取决于应用程序本身的发送和接收,但是TCP协议的通信则要受到协议栈的影响,应用程序发出了的数据并不一定等于发到了网络,比如Nagel算法就会影响实际发送。

    5.3.通讯行为

    你真的希望数据发出后就不管了吗?如果不是,那就使用TCP,不要自己实现确认和连接,当然在短连接情况下,你要仔细权衡TCP握手的开销和你自己实现的确认的开销。
    以DNS为例,这明显不是一个发后不管的应用,但是DNS客户端可以在一定时间没有收到回复后,再发出另一次查询,这并不影响最终的结果,这只是一个基础设施类型的单点查询任务,并不是电脑前用户最终的任务,因此使用UDP完全可以,但是对于HTTP就不一样了,HTTP本质上类似一次内容传输,然后浏览器解析传来的内容并给予展示,这对格式有严格的要求,并且事先并不知道结果的大小,结果的格式更是不固定,因此稍有差错就会影响到浏览器的解析。一次HTTP通信并不是一对一应用通信,而是牵扯到很多其它应用,比如服务器端的cgi以及客户端的script,因此绝对需要精确传输,此时就不能用UDP,即使是短连接也是要用TCP的。

    5.4.多点通讯

    我们知道,TCP是一个有连接的通信协议,在实际传输前,你必须和通信目的地建立一个双向的连接,并且只能和唯一的目的地建立连接,那么如果我们想将数据传给多个目的地,那么我们就需要建立多个这样的连接,在TCP之上,实现多点通信并不容易,这是TCP的握手协议以及挥手协议决定的。
    对于UDP,由于没有连接,就很好实现多点通信,对于使用了有连接的UDP,完全可以使用DNAT或者负载均衡之类的技术来实现多点通信。由于UDP协议不需要建立连接,那么完全可以向一个组播地址发送数据或者轮转地向多个目的地持续发送相同的数据。

    5.5.数据边界

    UDP是基于数据报的,这也就是说,每一个UDP包都是有边界的,这是和流式通信最大的不同,对于TCP而言,完全按照数据本身来界定边界,而对于UDP而言,则完全按照收发双方每次通信的实际内容界定边界。

    5.6.即已存在的事实

    我们在两个著名的开源代码中会遇到用UDP实现TCP的功能,它们是OpenSSL和OpenVPN,对于OpenSSL,DTLS完全是为了给基于UDP的应用提供安全保护而存在的,既然叫传输层安全,那就要要包容整个传输层(实际上,SSL协议在分层意义上跟TCP/IP的传输层一点关系都没有),对于OpenVPN,是历史原因才自己实现确认和重传的,那时还没有DTLS可以借鉴,这是无奈的。因此大家不要轻易把这两个事件作为可以借鉴的事实,在借鉴一件事的时候,一定要考虑它的历史背景,读史使人明智,事实在于如此。

    5.7.结论

    因此,只有你确认以下事实的时候,使用udp才是明智的

    5.7.1.你的应用完全是udp完成,或者你不在乎tcp会受到的影响

    5.7.2.你对网络状态很熟悉,确保udp网络中没有氓流行为,疯狂抢带宽

    5.7.3.通信双方配置,负载匹配或者自己手工解决了这些问题

    5.7.4.数据事实证明TCP真的比UDP更低效率或者你宗教般痴迷于UDP的高效率

    5.7.5.你不在乎上述4点或者你根本不懂网络

    5.7.6.TCP实在不方便实现多点传输的情况



    展开全文
  • 深入理解TCP、UDP协议及两者的区别

    万次阅读 多人点赞 2018-11-14 13:03:24
    一、TCP协议: 位于传输层, 提供可靠的字节流服务。所谓的字节流服务(Byte Stream Service) 是指, 为了方便传输, 将大块数据分割成以报文段(segment) 为单位的数据包进行...所以,TCP连接相当于两根管道(一...

    GitHub:https://github.com/JDawnF

    一、TCP协议:

           位于传输层, 提供可靠的字节流服务。所谓的字节流服务(Byte Stream Service) 是指, 为了方便传输, 将大块数据分割成以报文段(segment) 为单位的数据包进行管理。 而可靠的传输服务是指, 能够把数据准确可靠地传给对方。 即TCP 协议为了更容易传送大数据才把数据分割, 而且 TCP 协议能够确认数据最终是否送达到对方。所以,TCP连接相当于两根管道(一个用于服务器到客户端,一个用于客户端到服务器),管道里面数据传输是通过字节码传输,传输是有序的,每个字节都是一个一个来传输。

    (1)、三次握手:握手过程中使用了 TCP 的标志(flag) —— SYN(synchronize) 和ACK(acknowledgement) 。

    • 第一次握手:建立连接时,客户端A发送SYN包(SYN=j)到服务器B,并进入SYN_SEND状态,等待服务器B确认。
    • 第二次握手:服务器B收到SYN包,必须确认客户A的SYN(ACK=j+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器B进入SYN_RECV状态。
    • 第三次握手:客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK(ACK=k+1),此包发送完毕,完成三次握手。

    若在握手过程中某个阶段莫名中断, TCP 协议会再次以相同的顺序发送相同的数据包。
     (2)、四次挥手:由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。先进行关闭的一方将执行主动关闭,而另一方被动关闭。

    • 客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送。
    • 服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。
    • 服务器B关闭与客户端A的连接,发送一个FIN给客户端A。
    • 客户端A发回ACK报文确认,并将确认序号设置为收到序号加1。

    三次握手和四次挥手:在TCP连接中,服务器端的SYN和ACK向客户端发送是一次性发送的,而在断开连接的过程中, B端向A
    端发送的ACK和FIN是分两次发送的。因为在B端接收到A端的FIN后, B端可能还有数据要传输,所以先发送ACK,等B端处理完自己的事情后就可以发送FIN断开连接了。

    (3)、深入理解TCP连接: 

    由于TCP是全双工的,因此在每一个方向都必须单独关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个FIN只意味着这个方向上没有数据流动,一个TCP连接在接收到一个FIN后仍能发送数据。 首先进行关
    闭的一方将执行主动关闭,而另一方执行被动关闭。
    TCP协议的连接是全双工连接,一个TCP连接存在双向的读写通道。简单来说,是“先关读,再关写” ,总共需要4个阶段。以客户机发起关闭连接为例:1.服务器读通道关闭;2.客户端写通道关闭;3.客户端读通道关闭;4.服务器写通道关闭。
    关闭行为是在发起方数据发送完毕之后,给对方发出一个FIN(finish)数据段,直到接收到对方发送的FIN,且对方收到了接收确认的ACK之后,双方的数据通信完全结束,过程中每次都需要返回确认数据段ACK。

    (4)、TCP使用滑动窗口机制来进行流量控制。
    建立连接时,各端分配一个缓冲区用来存储接收的数据,并将缓冲区的尺寸发送给另一端。接收方发送的确认消息中包含了自己剩余的缓冲区尺寸。剩余缓冲区空间的数量叫做窗口。其实就是建立连接的双虎互相知道彼此剩余的缓冲区大小。

     (5)、拥塞控制

    拥塞控制:防止过多的数据注入到网路中,这样可以使网络中的路由器或链路不至于阻塞。拥塞控制是一个全局性的过程,和流量控制不同,流量控制是点对点的控制。

    1、慢开始:发送方维持一个叫做拥塞窗口cwnd(congestion window)的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态的变化。发送方让自己的发送窗口等于拥塞窗口,另外考虑到接收方的接收能力,发送窗口可能小于拥塞窗口。思路就是:不要一开始就发送大量的数据,先试探一下网络的拥塞程度,也就是说由小到大增加拥塞窗口的大小。

    为了防止cwnd增长过大引起网络拥塞,还需要设置一个慢开始门限ssthresh状态变量。 ssthresh的方法如下:
    当cwnd < ssthresh时,开始使用慢开始算法;当cwnd > ssthresh, 改用拥塞避免算法;当cwnd = ssthresh时,慢开始与拥塞算法任意。
     2.拥塞避免:

    拥塞避免算法让拥塞窗口缓慢增长,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是加倍,这样拥塞窗口按照线性规律缓慢增长。无论是在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其根据就是没有收到确认,虽然没有收到确认可能是其他原因的分组丢失,但是因为⽆法判定,所以都当作拥塞处理),就把慢开始门限设置为出现拥塞时的发送窗口的一半,然后把拥塞窗口设置为1,执行慢开始算法:

    此外,还有快速重传和快速恢复,停止-等待协议,回退N帧协议,选择重传协议等。 

    二、UDP协议:

    无连接协议,也称透明协议,也位于传输层。

    两者区别:

    1) TCP提供面向连接的传输,通信前要先建立连接(三次握手机制); UDP提供无连接的传输,通信前不需要建立连接。
    2) TCP提供可靠的传输(有序,无差错,不丢失,不重复); UDP提供不可靠的传输。
    3) TCP面向字节流的传输,因此它能将信息分割成组,并在接收端将其重组; UDP是面向数据报的传输,没有分组开销。
    4) TCP提供拥塞控制和流量控制机制; UDP不提供拥塞控制和流量控制机制。


    三、长连接和短连接

           HTTP的长连接和短连接本质上是TCP长连接和短连接。HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议。 IP协议主要解决网络路由和寻址问题,TCP协议主要解决如何在IP层之上可靠地传递数据包,使得网络上接收端收到发送端所发出的所有包,并且顺序与发送顺序一致。TCP协议是可靠的、面向连接的。

    在HTTP/1.0中默认使用短连接。也就是说,客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。当客户端浏览器访问的某个HTML或其他类型的Web页中包含有其他的Web资源(如JavaScript文件、图像文件、CSS文件等),每遇到这样一个Web资源,浏览器就会重新建立一个HTTP会话。

    而从HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头加入这行代码:

    Connection:keep-alive
    

    在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接需要客户端和服务端都支持长连接。

    HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。

    https://www.cnblogs.com/gotodsp/p/6366163.html

    此外,如果想更进一步学习网络相关的知识,可以参照:https://blog.csdn.net/striveb/article/details/84062700

     

    觉得有收获的,可以来一波赞赏!

    展开全文
  • 基于UDP协议的服务器

    万次阅读 2018-06-23 01:13:32
    在撸我们的服务器之前,先好好给大家好好理一理套接字这块的一些知识和概念。 先问问你自己,什么是端口号?这个概念可不是一个模模糊糊的东西 端口号:标识特定主机上唯一一个进程的标识符 是不是和进程id...

    本博客已弃用,当时存在一些小细节错误后期也不再修改了

    欢迎来我的新博客

    在撸我们的服务器之前,先好好给大家好好理一理套接字这块的一些知识和概念。


     先问问你自己,什么是端口号?这个概念可不是一个模模糊糊的东西

    端口号:标识特定主机上唯一一个进程的标识符

    是不是和进程id(pid)很像,没错,确实就是很像,因为进程id是也用来标识一个主机上唯一的一个进程,我们通过某个进程的进程id,可以对该进程进行几乎所有操作,如进程控制,进程间通信等等。而端口号和它的区别就在于:进程id所有进程一定都会有,而端口号却不是所有进程都会有,端口号是需要在不同主机间进行通信时才会绑定给参与通信的某个进程的一个标识符,也就是说,端口号是在两台主机间时才会有的概念和标识,但是进程id是在这个进程被创建出后一直伴随到它死亡(某种程度上就和一个人的名字一样),这个进程id才能被新创建的进程使用。

    个人感觉有个很形象的例子:在一个学校里,每个学生都拥有学号,并且是从你成为这个学校的学生那一刻起就有了,这个学号也能唯一的来标识你,对于学校的管理层来说,他们只要拿到你的学号,就可以得到你的所有信息,并且可以进行相关事宜的安排,这就像进程id。假设这个学校里有一批学生,他们是被学校任命去长期与其他学校学生进行交流的一批人,学校又给这一批人分配了一些编号,这些编号又能唯一标识这些人,这就像端口号。不知道你明白了没,反正我觉得很形象了(๑•̀ㅂ•́)و✧

    关于端口号再扩展一点重要的东西

    端口号的划分:

    0 - 1023: 知名端口号, HTTP, FTP, SSH等这些广为使用的应用层协议, 他们的端口号都是固定的,也就是你不能用的。

    1024 - 65535: 操作系统动态分配的端口号. 客户端程序的端口号, 就是由操作系统从这个范围分配的,也就是你能用的。

    这些也算是一个程序员的常识了,记不住也混个眼熟吧
    ssh服务器, 使⽤用22端⼝
    ftp服务器, 使⽤用21端⼝(更具体的话是20和21) 
    telnet服务器, 使⽤用23端⼝ 
    http服务器, 使⽤用80端⼝ 
    https服务器, 使⽤用443 

    需要注意的是在TCP/IP协议中, 用 "源IP", "源端口号", "目的IP", "目的端口号", "协议号" 这样一个五元组来标识一个通信(可以通过netstat -n查看)。

    关于端口号,有常见的两个问题

    1. 一个进程是否可以绑定多个端口号?

    2. 一个端口号是否可以被多个进程绑定?

    再来说说啥是IP地址呢?是IP地址到底是个用来干什么的东西呢?为什么要有它?

    IP地址:用来标识网络中,接入公网的唯一一台主机

    这个时候,你肯定可以理解,一台主机的IP地址加上其上的一个端口号,可以在网络中唯一的标识特定主机上的一个特定进程!套接字(socket)是一个翻译过来的词,由于网络中的套接字技术本身也是一种抽象出来的概念,其理解没有一个绝对的说法,其最好的理解就是:IP地址+端口号


    关于UDP协议

    说到UDP当然是先好好说说它的三大特点

    • 无连接: 知道对端的IP和端口号就直接进⾏行传输, 不需要建立连接; 
    • 不可靠: 没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方, UDP协议层也不会给应用层返回任何错误信息; 
    • 面向数据报: 不能够灵活的控制读写数据的次数和数量;

    我们知道,在通信技术不发达的时代,寄信是人类最常用的通信方式,UDP协议某些程度上和寄信挺像的

    • 无连接:写信的时候,你知道知道对方的邮政编码,对方知道寄信人,就能写信了,别的都不用管
    • 不可靠:写信这种通信方式是相当不可靠的(我们的UDP还是比写信可靠很多很多的),如果邮递员遇到恶劣天气无法前往就放弃送这封信了,或者邮递员在路上把你的信弄丢了,都会到导致信寄不到,也就是导致通信的失败,而邮递员也不会去告诉你,信没送到,毕竟那么多封信嘛,他根本就知道,这样,寄信人就傻傻的发,收信人就傻傻的收,有时候后果还挺严重啊
    • 关于面向数据报这一特点在寄信中不好类比,在我们的网络通信中是这样:无论应用层交给UDP多长的报文, UDP都原样发送, 既不会拆分,也不会合并(比如用UDP传输100个字节的数据: 如果发送端调用一次sendto, 发送100个字节, 那么接收端也必须调用对应的一次recvfrom, 接收100 个字节; 而不能循环调⽤用10次recvfrom, 每次接收10个字节)

    特别注意:一个UDP能传输的数据最大长度是64K(由UDP数据报结构决定的), 然而64K在当今的互联网环境下, 这是一个非常小的数字。如果我们需要传输的数据超过64K, 就需要在应用层手动的分包, 多次发送, 并在接收端手动拼装。UDP协议虽然具有接收缓冲区,但是其接收缓冲区不保证接收顺序,也就是未必和发送顺序一样,因此这个问题如何解决也是程序员在应用层要做的。

    UDP协议至今都是传输层的两大协议之一就是因为它的应用仍然非常广泛,它虽然有一些上面说到的缺点(TCP都没有),但是也有自己不可取代的优点:首先,UDP比TCP要快,虽然TCP没有UDP的那些缺点,但是TCP的三次握手建立连接、四次挥手断开连接、确认、窗口、重传、拥塞控制等机制无疑会导致TCP的速度是比不上UDP的,其次,没有这些机制,UDP也更不容易被攻击,因为UDP不需要这么多机制,那么为了保证其安全需要注意的方面也会相对少一些,能被他们利用的漏洞也就更少,当然UDP也是无法避免被攻击的,只是相比TCP之下更不容易。

    比如QQ中的大多数服务,都是用的UDP协议。

    基于UDP的应用层协议

    • NFS: 网络⽂文件系统 
    • TFTP: 简单文件传输协议 
    • DHCP: 动态主机配置协议 
    • BOOTP: 启动协议(用于无盘设备启动) 
    • DNS: 域名解析协议 

    当然还有咱们自己写基于的基于UDP的相关程序某种程度上也是UDP的应用层协议


    下面咱们开始撸一个很简单的echo(回显)服务器,这个服务器咱们要做到的是服务端接收客户端发来的内容并显示,并且把该内容发回客户端,客户端再显示一次

    服务器要做的事情就是:接收内容,并显示,然后发回客户端

    客户端要做的事情就:发送内容,再接收服务器的回显,再显示出来

    那么服务器代码的思路就是这样:

    创建套接字(socket)-->填充本地信息(sockaddr_in)-->把本地信息(套接字)与socket(这个我们在这区分一下就不叫它套接字了)一起绑定到操作系统内部,也就是把socket与IP地址加端口号绑定在一起(bind)-->接收(recvfrom)和回发(sendto)

    #include <stdio.h>                                                                                                                          
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <string.h>
    #include <arpa/inet.h>
    #include <stdlib.h>
    
    
    int main(int argc,char* argv[])
    {
        if(argc != 3)
        {
            printf("Usage %s [ip] [port]\n",argv[0]);
            return 1;
        }
    
        int sock = socket(AF_INET,SOCK_DGRAM,0);//协议IPV4 udp传输协议
        if(sock < 0)
        {
            perror("socket");
            return 2;
        }
    
        printf("sock: %d\n",sock);
    
        //填充本地信息
        struct sockaddr_in local;
        local.sin_family = AF_INET;
        local.sin_port = htons(atoi(argv[2]));  //把主机序列的字符串端口号转换成整型  然后转换为二子皆网络端口号 因为网络端口号是两个字节所以用s
        local.sin_addr.s_addr = inet_addr(argv[1]);  //把点分十进制字符串IP地址转换为网络字节序的四字节整型IP地址
        
        if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0)    //把用户栈上的local绑定到操作系统内部
        {
            perror("bind");
            return 3;
        }
    
        char buf[1024];
        while(1)
        {
            struct sockaddr_in client;
            socklen_t len = sizeof(client);
            //收到的东西放到buf里
            ssize_t s = recvfrom(sock, buf, sizeof(buf)-1,0,(struct sockaddr*)&client,&len);//通过client带回的信息知道是谁连接了我,我后面要发送
            if(s > 0)
            {
                buf[s] = 0;                                                                  
                //打印出客户端的IP地址和网络端口号,并用这两个函数将其转换成我们想看到的样子,并打印出client发过来的内容
                printf("[%s:%d]: %s\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port),buf);
                sendto(sock,buf,strlen(buf),0,(struct sockaddr*)&client,sizeof(client));//把buf中的内容发回客户端                               
            }
        }
    
    }
    

     

    客户端代码的思路:

    创建套接字(socket)-->填充本地信息(sockaddr_in)-->发送(sendto)和接收回显(recvfrom)

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <string.h>
    #include <arpa/inet.h>
    #include <stdlib.h>
    #include <unistd.h>
    //192.168.X.X 8080
    
    int main(int argc,char* argv[])
    {
        if(argc != 3)
        {
            printf("Usage %s [ip] [port]\n",argv[0]);
            return 1;
        }
    
        int sock = socket(AF_INET,SOCK_DGRAM,0);//协议IPV4 udp
        if(sock < 0)
        {
            perror("socket");
            return 2;
        }
    
        printf("sock: %d\n",sock);
    
        //填充本地信息
        struct sockaddr_in server;
        server.sin_family = AF_INET;
        server.sin_port = htons(atoi(argv[2]));  //把主机序列的字符串端口号转换成整型  然后转换为二子皆网络端口号 因为网络端口号是两个字节所以用short
        server.sin_addr.s_addr = inet_addr(argv[1]);  //把点分十式十进制字符串IP地址转换为网络字节序的四字节整型IP地址
        
        //客户端的端口号不应该绑定,这样不合适!
        /*if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0)    //把用户栈上的local绑定到操作系统内部
        {
            perror("bind");
            return 3;
        }*/
    
        char buf[1024];
        while(1)  //先读数据,再收数据
        {
            printf("Please Enter:");
            fflush(stdout);
            ssize_t s = read(0,buf,sizeof(buf)-1);  //从标准输入读
            if(s > 0)
            {
                buf[s-1] = 0;   //处理\n                                                               
                sendto(sock,buf,strlen(buf),0,(struct sockaddr*)&server,sizeof(server));//把buf中的内容发送到服务端
                //发送完后再接受服务器发回来的消息
                ssize_t _s = recvfrom(sock, buf, sizeof(buf)-1,0,NULL,NULL);//因为我们的客户端收到的数据一定从服务器发过来,不接受发送者也知道是谁发来的
                if(_s > 0)
                {
                    buf[_s] = 0;                                                                  
                    printf("server echo: %s\n",buf);
                }
            }
        }
    
    }
    

    Makefile

    .PHONY:all
    all:udp_server udp_client
    
    udp_server:udp_server.c
    	gcc -o $@ $^ 
    
    udp_client:udp_client.c
    	gcc -o $@ $^ -static
    
    .PHONY:clean
    clean:
    	rm -f udp_client udp_server
    

    gcc默认动态链接,因此我们的客户端代码要加上-static采用静态链接保证了客户端的可移植性,既是一个好习惯也方便我们可以在两台主机测试,不依赖本地库文件

    最后,用一台机器测试的用时候服务器和客户端的IP地址都用127.0.0.1(本地回环),端口号就都用8080(这个随意,只要是能用的就行)

    我写的这个是个非常简单的基于UDP的服务器,但是UDP协议的本质就是这样了,由这个你也能拓展出很多东西,比如,你把客户端发过来的又转发给另一个客户端,然后两个客户端之间互相回显,这就可以一对一聊天啦,服务器给所有连接的客户端回显,就是聊天室。

    代码点我

    展开全文
  • TCP 和 UDP 的区别

    万次阅读 多人点赞 2018-08-04 21:57:42
    前言 UDP TCP TCP 的三次握手 TCP 四次挥手 累计确认 顺序问题和丢包问题 流量控制的问题 拥塞控制的问题 ...TCP 是面向连接的,UDP 是面向无连接UDP程序结构较简单 TCP 是面向字节流的,UDP 是基于...
  • UDP协议开发

    千次阅读 2018-06-14 15:49:54
    电网数据采用UDP协议,通过监狱局域网,向用户指定的5个IP地址的某端口,同时发送,各IP地址收到的数据相同。因为是第一次使用网络数据报进行开发,因此遇到了许多的坑。在这里把遇到的问题组织成一个文档,重新理解...
  • UDP协议

    2015-09-27 18:29:24
    UDP特点 UDP首部格式及各字段意义
  • TCP协议和UDP协议的区别及其应用

    千次阅读 多人点赞 2018-07-02 19:34:45
    下面是TCP和UDP的简单程序: 简单的TCP网络程序 https://blog.csdn.net/qq_37941471/article/details/80738319 ...接着我们通过这两个协议来更直接的理解一下TCP协议和UDP协议: 这两个协议...
  • TCP协议与UDP协议

    千次阅读 2019-02-19 19:30:54
    首先咱们弄清楚,TCP协议和UCP协议与TCP/IP协议的联系,很多人犯糊涂了,一直都是说TCP/IP协议与UDP协议的区别,我觉得这是没有从本质上弄清楚网络通信! TCP/IP协议是一个协议簇。里面包括很多协议的。UDP只是其中...
  • 终于懂了TCP和UDP协议区别

    万次阅读 多人点赞 2020-03-26 12:03:28
    终于懂了TCP和UDP协议区别
  • 从事C++服务后台开发4年多,主要负责手Q游戏中心后台基础系统、复杂业务系统开发,主导过手Q游戏公会、企鹅电竞App-对战系统等项目的后台系统设计,丰富的后台架构经验。 责编:钱曙光,关注架构和算法领域,...
  • IP头、TCP头、UDP头详解以及定义

    万次阅读 多人点赞 2013-01-24 13:47:25
    一、MAC帧头定义 /*数据帧定义,头14个字节,尾4个字节*/ typedef struct _MAC_FRAME_HEADER {  char m_cDstMacAddress[6]; //目的mac地址  char m_... //上一层协议类型,如0x0800代表上一层是IP...
  • UDP理论详解

    万次阅读 2016-06-28 21:54:40
    我们已经讲解了物理层、连接层和网络层... layer),协议的种类又开始繁多起来(比如TCP、UDP、SCTP等)。这就好像下面的大树,根部(连接层)分叉很多,然后统一到一个树干(网络层),到了树冠(传输层)部分又开始开始分叉,
  • UDP协议简介

    2019-05-11 22:42:52
    UDP是数据报不是流,所以不会像TCP那样分包的概念,不管数据包是怎么样的就直接发送出去。所以才会产生IP分片,而TCP会进行流量控制,会分包组合,所以一般不会导致很多的IP分片产生 UDP不提供可靠性,直接发出去...
  • UDP协议 大多数的应用程序都像之前介绍的一样使用 TCP 协议来收发数据,但当然也例外。有些应用程序不使用 TCP 协议,而是使用 UDP 协议来收发数据。 下面就简单介绍一下 UDP 协议。其实 TCP 中就包含了 UDP...
  • UDP协议详细解析

    千次阅读 2019-03-14 18:52:53
    基本定义:UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。UDP...
  • 一、用户数据报协议UDP)简介 UDP是一种保留消息边界的简单的面向数据报的传输层协议 UDP特性 它不提供差错纠正、队列管理、重复消除、流量控制和拥塞控制 不提供差错纠正:它把应用程序传给IP层的数据发送...
  • 面试题:TCP协议与UDP协议的区别

    万次阅读 多人点赞 2016-07-19 14:43:16
    TCP(Transmission Control Protocol,传输控制协议)是面向连接协议,也就是说,在收发数据前,必须和对方建立可靠的连接。一个TCP连接必须要经过三次“对话”才能建立起来,其中的过程非常复杂,只简单的描述下...
  • UDP协议解析

    千次阅读 2018-07-18 16:48:06
    UDP称为用户数据包协议,是传输层的协议。他的功能其实就是在ip的数据报服务之上添加了复用、分用和差错检验。 特点: 无连接,即发送数据之前不需要建立连接。无连接的好处就是快,省内存空间。因为维护连接需要...
  •  UDP协议全称是用户数据报协议[1],在网络中它与TCP协议一样用于处理数据包,但不同于TCP的是,UDP是一种无连接的协议。。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP不提供数据包分组、组装和不...
  • UDP

    千次阅读 2018-08-13 22:54:34
     用户数据保协议(User Datagram Protocol,UDP)是开放系统互联模型(Open System Interconnection,OSI)中传输层协议的一种,是一种保留消息边界的简单的面向数据报的协议UDP不提供差错纠正、队列管理、重复...
  • 一、下图是典型的UDP客户端/服务器通讯过程 下面依照通信流程,我们来实现一个UDP回射客户/服务器  #include  #include  ssize_t send(int sockfd, const void *buf, size_t len, int flags);  ssize_t ...
  • 知道TCP是面向连接的提供可靠性服务的传输层协议,今天讲下同属于传输层的另一个协议——UDP。 正文 1 什么是UDPUDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open ...
  • UDP协议是User Datagram Protocol的简写,它是无连接的,不可靠的网络协议。本章将介绍如何使用UDP协议进行程序设计,对UDP编程的基本框架进行介绍并给出程序设计的例子。本章中使用比较大的篇幅对UDP协议的程序设计...
  • 7. 传输层协议(TCP、UDP

    万次阅读 2020-09-07 01:54:58
    TCP(Transmission Control Protocol)传输控制协议; TCP报文结构; TCP三次握手; TCP重传机制; TCP四次挥手; TCP端口号; UDP(User Datagram Protocol)用户数据协议UDP报文结构。
  • UDP/IP传输协议

    千次阅读 2019-06-29 21:15:23
    一、传输层最重要的协议就是TCP和UDP。...UDP协议同样以数据报(datagram)的方式进行数据传输,而且UDP协议提出了端口(port)的概念。IP协议进行的是IP地址到IP地址的传输。但是每台计算机多个通信通道,并将多个通...

空空如也

1 2 3 4 5 ... 20
收藏数 423,458
精华内容 169,383
关键字:

udp 协议 有 长连接的概念吗