《TCP/IP网络编程》 尹圣雨
P101~P114
1 理解UDP
UDP提供的是不可靠的数据传输服务。
UDP结构上比TCP简洁,不会发送类似ACK的应答消息,不会像SEQ那样给数据包分配序号。因此UDP性能有时会比TCP更高。编程实现UDP也比TCP简单。另外,UDP的可靠性比不上TCP,但也不会像想象中那么频繁地发生数据损毁。
UDP作用?
为提供可靠的数据传输服务,TCP在不可靠的IP层进行流控制,而UDP就缺少这种流控制机制。
UDP和TCP的差异只在于流控制机制。TCP的生命在于流控制。
TCP的速度无法超过UDP,但是在收发某些类型的数据时有可能接近UDP。例如每次交换的数据量越大,TCP的传输速率就越接近UDP的传输速率。
UDP内部工作原理 P102
IP作用是让离开主机B的UDP数据包准确传递给主机A。但把UDP包最终交给主机A的某一UDP套接字的过程是由UDP完成的。
UDP最重要的作用就是根据端口号将传到主机的数据包交付给最终的UDP套接字。
UDP的高效使用
UDP并非每次都快于TCP,TCP比UDP慢的原因通常有以下两点:
1)收发数据前后进行的连接设置及清除过程。
2)收发数据过程中为保证可靠性而添加的流控制。
如果收发的数据量小但需要频繁连接时,UDP比TCP更高效。
2 实现基于UDP的服务器端/客户端
(1)UDP中的服务器端和客户端没有连接
不必调用TCP连接过程中调用的listen函数和accept函数,UDP只有创建套接字的过程和数据交换过程。
(2)UDP服务器端和客户端均只需1个套接字
TCP中,套接字间应该是一对一高效。若要向10个客户端提供服务,则除了守门的服务器套接字外,还需要10个服务器端套接字。但是在UDP中,不管是服务器端还是客户端都只需要1个套接字。只需要1个套接字就能和多台主机通信。
(3)基于UDP的数据I/O函数
创建好TCP套接字后,传输数据时无需再添加地址信息。因为TCP套接字将保持与对方套接字的连接。即TCP套接字知道目标地址的信息。 而UDP套接字不会保持这种连接状态,因而每次传输数据都要添加目标地址信息。
填写地址并传输数据时的函数
#include<sys/socket.h>
ssize_t sendto(int sock, void *buff,size_t nbytes,int flags,struct sockaddr *to,socklen_t addrlen);
成功时返回传输的字节数,失败时返回-1.
sock 用于传输数据的UDP套接字文件描述符
buff 保持待传输数据的缓冲地址值
nbytes 待传输的数据长度,以字节为单位
flags 可选项参数,若没有则传递0
to 存有目标地址信息的sockaddr结构体变量的地址值
addrlen 传递给参数to的地址值结构体变量长度
接收UDP数据的函数
#include<sys/socket.h>
ssize_t recvfrom(int sock, void *buff,ssize_t nbytes,int flags, struct sockaddr *from,socklen_t * addrlen)
成功时返回接收的字节数,失败时返回-1.
sock 用于接收数据的UDP套接字文件描述符
buff 保存接收数据的缓冲地址值
nbytes 可接收的最大字节数,无法超过参数buff所指的缓冲大小
flags 可选项参数,若没有则传递0
from 存有发送端地址信息的sockaddr结构体变量的地址值
addrlen 保存参数from的结构体变量长度的变量地址值
(4)基于UDP的回声服务器端/客户端 P105~P108
(5)UDP客户端套接字的地址分配
UDP客户端缺少把IP和端口分配给套接字的过程。TCP客户端调用connect函数自动完成此过程,而UDP中连能承担相同功能的函数调用语句都没有。
UDP程序中,调用sento函数传输数据前应完成对套接字的地址分配工作,因此调用bind函数。bind函数不区分TCP或者UDP,也就是说,在UDP程序中同样可以调用。另外如果调用sendto函数时发现尚未分配地址信息,则在首次调用sendto函数时给相应套接字自动分配IP和端口。而且此时分配的地址一直保留到程序结束为止,因此也可用来与其他UDP套接字进行数据交换。IP用主机IP,端口号选尚未使用的任意端口号。
调用sendto函数时自动分配IP和端口号,UDP客户端中无需额外的地址分配过程。
3 UDP的数据传输特性和调用connect函数
(1)存在数据边界的UDP套接字
TCP传输的数据不存在数据边界,表示“数据传输过程中调用I/O函数的次数不具有任何意义”。
UDP数据传输中存在数据边界,传输中调用I/O函数的次数非常重要。因此,输入函数的调用次数应和输出函数的调用次数完全一致,这样才能保证接收全部已发送数据。
P109~P111简单示例。
UDP数据报:UDP套接字传输的数据包又称为数据报,实际上数据报也属于数据包的一种。只是与TCP包不同,其本身可以成为1个完整数据。这与UDP的数据传输特性有关,UDP中存在数据边界,1个数据包即可成为有关完整数据,因此称为数据报。
TCP套接字中需注册传输数据的目标IP和端口号,而UDP中则无需注册。因此通过sendto函数传输数据的过程大致分为以下3个阶段
第一阶段:向UDP套接字注册目标IP和端口号
第二阶段:传输数据
第三阶段:删除UDP套接字中注册的目标地址信息
每次调用sendto函数时重复上述过程,每次都变更目标地址,因此可以重复利用同一UDP套接字向不同目标传输数据。这种未注册目标地址信息的套接字称为未连接套接字。UDP默认为未连接套接字。
创建已连接UDP套接字只需针对UDP套接字调用connect函数
这并不意外这要与对方UDP套接字连接,这只是向UDP套接字注册目标IP和端口信息。