网络(2)UDP通信

今天学习了UDP网络编程,UDP属于无连接的通信,不用像TCP那样先建立连接,直接发数据包就行。优点是简单、开销小,缺点就是不可靠,发出去的数据对方不一定能收到,也没有重传机制。像直播、语音通话很多就会用UDP,允许丢一点点数据,优先保证速度。

UDP通信

UDP发送端:

  1. socket 创建套接字
  2. sendto 直接把数据发给目标地址

UDP接收端:

  1. socket 创建套接字
  2. bind 绑定本机IP和端口
  3. recvfrom 等待接收对方发来的数据
    注意:发送端可以不用bind,操作系统会自动随机分配端口;接收端必须bind,固定端口,别人才知道往哪个端口给你发消息。

函数接口:

  1. socket
    int socket(int domain, int type, int protocol);
    作用:创建通信端点,拿到一个文件描述符,后续收发数据都靠它。

domain:协议族,写AF_INET代表IPv4

type:套接字类型。SOCK_DGRAM就是UDP;SOCK_STREAM是TCP

protocol:一般直接填0,自动匹配对应协议

返回值:成功返回文件描述符,失败返回‑1。

  1. sendto
    ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
    const struct sockaddr *dest_addr, socklen_t addrlen);
    UDP发送数据专用函数。因为UDP没有连接,每次发送都要带上目标的IP和端口。

sockfd:socket返回的文件描述符

buf:要发送的数据缓冲区

len:要发送多少字节

flags:一般填0

dest_addr:目标主机的地址结构体,存对方IP+端口

addrlen:地址结构体的大小

返回值:成功返回实际发送的字节数,失败‑1。

  1. sockaddr_in结构体(IPv4地址)
    struct sockaddr_in {
    sa_family_t sin_family;
    in_port_t sin_port;
    struct in_addr sin_addr;
    };
    struct in_addr {
    uint32_t s_addr;
    };
    这个结构体用来装IP和端口。

sin_family:协议族,填AF_INET

sin_port:端口号,必须网络字节序

sin_addr.s_addr:IP地址,同样是网络大端字节序

编程里经常会强制转换成struct sockaddr*传给函数,这是接口的固定写法。

  1. htons

    uint16_t htons(uint16_t hostshort);

    主机字节序转网络大端字节序。

    我们电脑大多是小端存储,网络传输统一规定用大端。设置端口的时候必须调用这个函数做转换,不然端口号会错乱。

  2. inet_addr

    in_addr_t inet_addr(const char *cp);

    把字符串形式的IP,比如"192.168.1.100",转换成网络字节序的二进制IP,直接赋值给s_addr。

  3. bind

    int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

    把套接字和本机IP、端口绑定在一起。接收端必须bind。

    注意:

  4. 只能绑定自己本机的IP,不能绑定别的机器IP

  5. 同一个端口被别的程序占用,bind直接失败

返回值:成功0,失败‑1。

  1. recvfrom
    ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
    struct sockaddr *src_addr, socklen_t *addrlen);
    UDP接收数据。不仅拿到数据,还能拿到发送方的IP和端口,收到之后就知道是谁发过来的,后续可以回复对方。

buf:存放收到数据的缓冲区

len:缓冲区最大能收多少字节

src_addr:输出参数,会填充发送者的地址信息

addrlen:传入地址结构体大小,函数内部会修改

返回值:成功返回收到字节数,失败‑1。

  1. inet_ntoa
    char *inet_ntoa(struct in_addr in);
    和inet_addr反过来。把网络二进制IP,变回我们看得懂的字符串IP,打印日志的时候经常用。

UDP报文头部

UDP数据包头部一共8个字节:

源端口、目的端口、数据包长度、校验和,剩下全部是应用数据。

特点:

  1. 实现逻辑简单,代码写起来比TCP少很多
  2. 资源开销小,传输速度快
  3. 不可靠:没有确认机制,数据可能丢包、乱序,适合对实时性要求高,能接受少量丢包的场景。

总结:

  1. UDP无连接,发送端不需要connect,用sendto;接收端必须bind。
  2. 端口号一定要用htons转网络字节序,IP用inet_addr转换。
  3. sendto每次都要指定目标地址;recvfrom可以获取发送方地址。
  4. bind不能绑定别的主机IP,端口被占用会绑定失败。
  5. UDP优点速度快,缺点不可靠,不保证数据一定到达。
相关推荐
susplus17 分钟前
【linux应用软件编程】进程间的通信方式2【网络通信从入门到UDP编程】
linux·udp·ip
zcmodeltech23 分钟前
风力发电沙盘模型控制系统设计与灯光联动实现方案——基于STM32与Modbus RTU,服务范围覆盖全国的多场景风力发电沙盘模型定制
网络·数据库·stm32·单片机·嵌入式硬件·能源
离凌寒25 分钟前
一、关于软件定时器模拟任务运行总结
单片机·嵌入式硬件
智闲电子设计44 分钟前
STM32 硬件过流保护实战:比较器直连 BKIN,纳秒级关断不靠软件
stm32·单片机·嵌入式硬件
嵌入式阿蔡1 小时前
存储_14:嵌入式存储测试岗面试——可靠性/兼容/车规面试题与项目话术
单片机·嵌入式硬件·面试·嵌入式·存储
张小姐的猫1 小时前
【C++开发脚手架】 —— Jsoncpp上手
java·linux·开发语言·网络·c++·tcp/ip·udp
console.log('npc')1 小时前
火山引擎 Ark 平台模型部署与计费配置文档
网络·火山引擎
昌原的儿子LEO1 小时前
Linux网络编程:TCP/UDP与HTTP协议核心笔记
linux·网络·tcp/ip