【TCP/IP网络编程】:06基于UDP的服务器端/客户端

本篇文章简单描述了UDP传输协议的工作原理及特点。

理解UDP

UDP和TCP一样同属于TCP/IP协议栈的第二层,即传输层。

UDP套接字的特点

UDP的工作方式类似于传统的信件邮寄过程。寄信前应先在信封上填好寄信人和收信人的地址,之后贴上邮票放进邮筒即可。当然信件邮寄过程可能会发生丢失,我们也无法随时知晓对方是否已收到信件。也就是说信件是一种不可靠的传输方式,同样的,UDP所提供的也是一种不可靠的数据传输方式(以信件类比UDP只是通信形式上一致性,之前也以电话通信的方式类比了TCP的通信方式,而实际上从通信速度上来讲UDP通常是要快于TCP的;每次交换的数据量越大,TCP的传输速率就越接近于UDP)。因此,如果仅考虑可靠性,TCP显然由于UDP;但UDP在通信结构上较TCP更为简洁,通常性能也要优于TCP。

区分TCP和UDP最重要的标志是流控制,流控制赋予了TCP可靠性的特点,也说TCP的生命在于流控制。

UDP内部工作原理

与TCP不同,UDP不会进行流控制,其在数据通信中的作用如下图所示。可以看出,IP的作用就是让离开主机B的UDP数据包准确传递到主机A,而UDP则是把UDP包最终交给主机A的某一UDP套接字。UDP最重要的作用就是根据端口号将传输到主机的数据包交付给最终的UDP套接字。

数据包传输过程UDP和IP的作用

UDP的高效使用

TCP用于对可靠性要求较高的场景,比如要传输一个重要文件或是压缩包,这种情况往往丢失一个数据包就会引起严重的问题;而对于多媒体数据来说,丢失一部分数据包并没有太大问题,因为实时性更为重要,速度就成为了重要考虑因素。TCP慢于UDP主要在于以下两点:

  • 收发数据前后进行的连接及清理过程
  • 收发数据过程中为保证可靠性而添加的流控制

因此,如果收发的数据量小但需要频繁的连接时,UDP比TCP更为高效。

基于UDP的服务器端/客户端

和TCP不同,UDP服务器端/客户端并不需要在连接状态下交换数据,UDP的通信只有创建套接字和数据交换的过程。TCP套接字是一对一的关系,且服务器端还需要一个额外的TCP套接字用于监听连接请求;而UDP通信中,无论服务器端还是客户端都只需要一个套接字即可,且可以实现一对多的通信关系。下图展示了一个UDP套接字与两台主机进行数据交换的过程。

UDP套接字通信模型

基于UDP的数据I/O函数

TCP套接字建立连接之后,数据传输过程便无需额外添加地址信息,因为TCP套接字会保持与对端的连接状态;而UDP则没有这种连接状态,因此每次数据交换过程都需要添加目标地址信息。下面是UDP套接字数据传输函数,与TCP传输函数最大的区别在于,该函数需要额外添加传递目标的地址信息。

#include <sys/socket.h>

ssize_t sendto(int sock, void *buff, size_t nbytes, int flags, struct sockaddr *to, socklen_t addrlen);
    -> 成功时返回传输的字节数,失败时返回-1

由于UDP数据的发送端并不固定,因此,UDP套接字的数据接收函数定义了存储发送端地址信息的数据结构。

#include <sys/socket.h>

ssize_t recvfrom(int sock, void *buff, size_t nbytes, int flags, struct sockaddr *from, socklen_t addrlen);
    -> 成功时返回接收的字节数,失败时返回-1

基于UDP的回声服务器端/客户端

UDP通信函数调用流程

UDP不同于TCP,不存在请求连接和受理连接的过程,因此某种意义上并没有明确的服务器端和客户端之分。如下是示例源码。

 uecho_server

 uecho_client

示例代码运行结果

UDP客户端套接字的地址分配

从上述示例源码来看,服务器端UDP套接字需要手动bind地址信息,而客户端UDP套接字则无此过程。我们已经知道,客户端TCP套接字是在调用connect函数的时机,由操作系统为我们自动绑定了地址信息;而客户端UDP套接字同样存在该过程,如果没有手动bind地址信息,则在首次调用sendto函数时自动分配IP和端口号等地址信息。和TCP一样,IP是主机IP,端口号则随机分配(客户的临时端口是在第一次调用sendto 时一次性选定,不能改变;然而客户的IP地址却可以随客户发送的每个UDP数据报而变动(如果客户没有绑定一个具体的IP地址到其套接字上)。其原因在于如果客户主机是多宿的,客户有可能在两个目的地之间交替选择)。

UDP数据传输特性和connect函数调用

之前我们介绍了TCP传输数据不存在数据边界,下面将会验证UDP数据传输存在数据边界的特性,并介绍UDP传输调用connect函数的作用。

存在数据边界的UDP套接字

UDP协议具有数据边界,这就意味着数据交换的双方输入函数和输出函数必须一一对应,这样才能保证可完整接收数据。如下是验证UDP存在数据边界的示例源码。

 bound_hostA

 bound_hostB

示例代码运行结果

调用connect函数的UDP套接字

TCP套接字需要手动注册传输数据的目标IP和端口号,而UDP则是调用sendto函数时自动完成目标地址信息的注册,该过程如下

  • 第一阶段:向UDP套接字注册目标IP和端口号
  • 第二阶段:传输数据
  • 第三阶段:删除UDP套接字中注册的目标地址信息

每次调用sendto函数都会重复执行以上过程,这也是为什么同一个UDP套接字可和不同目标进行数据交换的原因。像UDP这种未注册目标地址信息的套接字称为未连接套接字,而TCP这种注册了目标地址信息的套接字称为已连接connected套接字。当需要和同一目标主机进行长时间通信时,UDP的这种无连接的特点则会非常低效。通过调用connect函数使UDP变为已连接套接字则会有效改善这一点,因为上述的第一阶段和第三阶段会占用整个通信过程近1/3的时间。

针对UDP套接字调用connect函数并非真的与目标UDP套接字建立连接,仅仅是向本端UDP套接字注册了目标IP和端口号信息而已。已连接的UDP套接字不仅可以使用之前的sendto和recvfrom函数,还可以使用没有地址信息参数的write和read函数。修改之前的ucheo_client代码为已连接UDP套接字如下。

 uecho_con_client

【TCP/IP网络编程】:06基于UDP的服务器端/客户端

原文地址:https://www.cnblogs.com/douyins/p/12117578.html

时间: 2024-08-02 20:56:41

【TCP/IP网络编程】:06基于UDP的服务器端/客户端的相关文章

TCP/IP网络编程之基于TCP的服务端/客户端(二)

回声客户端问题 上一章TCP/IP网络编程之基于TCP的服务端/客户端(一)中,我们解释了回声客户端所存在的问题,那么单单是客户端的问题,服务端没有任何问题?是的,服务端没有问题,现在先让我们回顾下服务端的I/O代码 echo_server.c --while ((str_len = read(clnt_sock, messag, 1024)) != 0) write(clnt_sock, messag, str_len);-- 接着,我们回顾客户端的代码 echo_client.c -- wr

TCP/IP网络编程 学习笔记_11 --多进程服务器端

并发服务器 首先,我们来假设有下面这样两种类型的服务器:第一种,第一个连接请求的受理时间为1s,第50个连接请求的受理时间为50s,第100个连接请求的受理时间为100s.即同时很多客服端连接,需要依次排队受理,但只要受理了,他们的服务时间平均只需1s.第二种,所有连接请求的受理时间不超过1s,但平均服务时间要2~3s. 即使有可能延长服务时间,我们实际网络编程中也一般选择第二种方式,使其可以同时向所有发起请求的客服端提供服务,以提高平均满意度.而且,网络程序中数据通信时间比CPU运算时间占比更

TCP/IP 网络编程 (抄书笔记 2) -- UDP

TCP/IP 网络编程 (抄书笔记 2) – UDP TCP/IP 网络编程 (抄书笔记 2) – UDP Table of Contents server client connect 来源: <TCP/IP 网络编程> 抄书: TCP 协议若要向 10 个客户端提供服务, 除了需要 listen 套接字外, 还需要 10 个服务器端套接字 (accept), 但是在 UDP 中, 不管是服务器端还是客户端都只需要 1 个套接字 udp 的 client 不需要 bind, 调用 sendt

《TCP/IP网络编程》

<TCP/IP网络编程> 基本信息 作者: (韩)尹圣雨 译者: 金国哲 丛书名: 图灵程序设计丛书 出版社:人民邮电出版社 ISBN:9787115358851 上架时间:2014-6-19 出版日期:2014 年6月 开本:16开 页码:1 版次:1-1 所属分类:计算机 > 计算机网络 > 网络协议 > TCP/IP 更多关于>>><TCP/IP网络编程> 编辑推荐 为初学者准备的网络编程 本书涵盖操作系统.系统编程.TCP/IP协议等多种

TCP/IP网络编程系列之四(初级)

TCP/IP网络编程系列之四-基于TCP的服务端/客户端 理解TCP和UDP 根据数据传输方式的不同,基于网络协议的套接字一般分为TCP和UDP套接字.因为TCP套接字是面向连接的,因此又称为基于流的套接字.在了解TCP之前,先了解一下TCP所属的TCP/IP协议栈. 如图所示,TCP/IP协议栈共分为4层,可以理解成数据收发分成了4个层次化过程. 链路层 它是物理链接领域标准化结果,也是最基本的领域,专门定义LAN.WAN.MAN等网络标准.若两台计算机通过网络进行数据交换,链路层就负责整个物

TCP/IP网络编程系列之三

TCP/IP网络编程系列之三-地址族与数据序列 分配给套接字的IP地址和端口 IP是Internet Protocol (网络协议)的简写,是为首发网络数据而分配给计算机的值.端口号并非赋予计算机值,而是为了区分程序中创建的套接字而分配给套接字的序号. 网络地址 网络地址分为IPV4和IPV6,分别你别为4个字节地址簇和6个字节地址簇.IPV4标准的4个字节的地址分为网络地址和主机地址,且分为A.B.C.D.E 等类型.一般很少用到E类型.如下图所示:net-id指网络ID,host-id指主机

TCP/IP网络编程系列之二

套接字类型与协议设置 我们先了解一下创建套接字的那个函数 int socket(int domain,int type,int protocol);成功时返回文件描述符,失败时返回-1.其中,domain是套接字使用中的协议族(Protocol Family)信息.type套接字类型里面的数据传输类型信息.protocol计算机通信中使用的协议信息. 协议族(Protocol Family) 协议族类型有: PE_INET IPV4 PE_INET6 IPV6 PF_LOCAL 本地通信的UNI

TCP/IP网络编程系列之一

概述 网络编程实际上就是编写程序使两台联网的计算机相互的交换数据.操作系统会提供名为“ 套接字 ”的部件.套接字是网络数据传输的软件设备,即使对网络数据传输原理不太熟悉也无关紧要.我们也能通过套接字完成数据传输,因此网络编程又叫套接字编程. 过程  我们可以把套接字理解为我们平时的电话机,我们先看一下套接字的创建过程: 首先你如果要和别人沟通肯定要安装好电话机才可以,所以对应套接字的是调用socket函数时进行对话. #include<sys/socket.h> int socket(int

TCP/IP网络编程系列之二(初级)

套接字类型与协议设置 我们先了解一下创建套接字的那个函数 int socket(int domain,int type,int protocol);成功时返回文件描述符,失败时返回-1.其中,domain是套接字使用中的协议族(Protocol Family)信息.type套接字类型里面的数据传输类型信息.protocol计算机通信中使用的协议信息. 协议族(Protocol Family) 协议族类型有: PE_INET IPV4 PE_INET6 IPV6 PF_LOCAL 本地通信的UNI