UDP协议

端口号

在网络通信过程中,用端口号来标识发送/接受数据的进程。

端口号的分类

  • 公认端口(Well Known Ports):范围从0到1023,这些端口紧密绑定于一些服务,如HTTP(80端口)、FTP(21端口)等。这些端口的通讯明确表明了某种服务的协议。

  • 注册端口(Registered Ports):范围从1024到49151,使用这类端口号必须在IANA上登记

  • 动态和/或私有端口(Dynamic and/or Private Ports):范围从49152到65535,理论上,不应为服务分配这些端口。但实际上,机器通常从1024起分配动态端口。

常用的端口号

FTPTELNETSMTPDNSTFTPHTTP
21/20(数据)2325536980
HTTPSMySQL
4433306

UDP首部格式

用户数据报UDP有2个字段,首部字段和数据字段。UDP的首部开销小,只有8个字节,由4个字段组成,每个字段都是2个字节。

length字段是用户数据报的长度,最小值是8,仅代表首部

image-20240526165957013

如果接受方UDP发现收到的端口号不正确的话,就丢弃这个报文,并由ICMP发送端口不可达的报文给发送方。

UDP的首部校验和,在计算的时候需要在UDP数据报前面加上12个字节的伪首部,伪首部的增加仅仅是为了计算校验和,在计算的时候,把首部和数据部分一起检验,在接收端,当UDP数据包到达时,接收端会按照相同的步骤重新计算校验和,并将结果与数据包中的校验和进行比较。

如果两者相同,则说明数据包在传输过程中没有发生错误;如果不同,则说明数据包在传输过程中可能已损坏,接收端可以选择丢弃该数据包或进行其他处理。

UDP协议首部的16位长度字段确实限制了单个UDP数据报的最大长度为65,535字节(即2^16 - 1,因为0是全零的保留值)。这个长度包括了UDP首部和UDP数据部分,但通常不包括IP首部。因此,实际可以传输的数据(即“有效载荷”)会小于这个值,因为还需要考虑到IP首部和可能的网络层封装开销。

在大多数现代互联网应用中,这个限制确实可能成为一个问题,因为许多应用需要传输远大于64KB的数据。为了解决这个问题,应用层确实需要实现分包(fragmentation)和重组(reassembly)的逻辑。

UDP缓存区

UDP没有像TCP那样的发送缓冲区来维护待发送数据的队列和流量控制。当应用层调用sendto函数发送UDP数据包时,数据会直接交给内核,由内核将数据封装成UDP数据报,并传递给网络层协议(如IP)进行后续的传输。

UDP具有接收缓冲区,但它与TCP的接收缓冲区在功能和行为上有很大不同。UDP的接收缓冲区主要用于临时存储从网络层接收到的UDP数据报,直到应用层调用recvfrom或类似的函数来读取这些数据。

然而,由于UDP是无连接的协议,它不保证数据包的顺序性。也就是说,即使发送端按顺序发送了多个UDP数据包,接收端也可能以不同的顺序接收到这些数据包。此外,UDP也不提供可靠性保证,所以如果数据包在传输过程中丢失或损坏,接收端将不会收到任何通知。

另外,如果UDP接收缓冲区满了,再到达的UDP数据报通常会被丢弃,而不会像TCP那样进行排队等待。这是因为UDP的设计目标就是提供无连接、不可靠的数据传输服务,所以它不会像在TCP中那样进行复杂的流量控制和拥塞控制。

UDP小例子

服务器端

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  

#define SERVER_PORT 8080
#define BUFFER_SIZE 1024

int main()
{
    int server_fd;
    char buffer[BUFFER_SIZE] = {0};
  
    if((server_fd = socket(AF_INET, SOCK_DGRAM, 0)) == 0)
    {
        perror("socket faild");exit(-1);
	}
    struct sockaddr_in server;
    int len = sizeof(server);
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons(SERVER_PORT);
    if(bind(server_fd, (struct sockaddr*)& server, sizeof(server)) < 0)
    {
        perror("bind faild");exit(-2);
	}
    //阻塞等待直到指定的长度
    if(recvfrom(server_fd, buffer, BUFFER_SIZE, MSG_WAITALL, 
     (struct sockaddr*)&address,(socklen_t*)& (sizeof(server)) < 0)
    {
        perror("recvfrom faild");exit(-3);
    }
    printf("client#%s:%s\n", inet_ntoa(server.sin_addr), buffer);
    close(server_id);
}

客户端

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  

#define SERVER_IP "127.0.0.1"
#define SERBER_PORT 8080
#define BUFFER_SIZE 1024

int main()
{
    int sock = 0;
    struct sockaddr_in ser;
    char buffer[BUFFER_SIZE] = {0};
    
    if(sock = socket(AF_INT, SOCK_DGRAM, 0) < 0)
    {
        exit(-1);
    }
    char* msg = "hello";
    ser.sin_family = AF_INET;
    ser.sin_port = htons(SERBER_PORT);
    ser.sin_addr.s_addr = iner_addr(SERVER_IP);
    
    sendto(sock, msg,strlen(msg),MSG_CONFIRM,
          (struct sockaddr*)& ser,sizeof(ser));
    close(sock);
    
}

sendto/recvfrom

#include <sys/types.h>  
#include <sys/socket.h>  
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,  
               const struct sockaddr *dest_addr, socklen_t addrlen);

#include <sys/types.h>  
#include <sys/socket.h>  
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,  
                 struct sockaddr *src_addr, socklen_t *addrlen);
  1. sockfd:要发送数据的套接字描述符。
  2. buf:指向要发送数据的缓冲区的指针。
  3. len:要发送数据的长度(以字节为单位)。
  4. flags:指定发送操作的可选标志位。通常设置为0,表示不使用任何特殊标志。
  5. dest_addr:指向目标地址信息的结构体指针,用于指定数据发送的目标地址和端口。
  6. addrlendest_addr结构体的长度。

基于UDP的应用层协议

  1. NFS: 网络文件系统
  2. TFTP: 简单文件传输协议
  3. DHCP: 动态主机配置协议
  4. BOOTP: 启动协议(用于无盘设备启动)
  5. DNS: 域名解析协议
  6. RIP:路由信息协议
  7. 流式多媒体通信
  8. VoIP是一种通过IP网络进行语音通信的技术。
  9. RTP是一个用于传输实时数据的协议,如音频、视频或模拟数据。

UDP总结

  1. 无连接:知道对端的IP和端口号就直接进行传输, 不需要建立连接
  2. 不可靠: 没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方, UDP协议层也不会给应用层返回任何错误信息;
  3. 面向数据报: 不能够灵活的控制读写数据的次数和数量,应用层交给UDP多长的报文,UDP就照样发送,所以应用程序必选好报文的大小。
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值