网络(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优点速度快,缺点不可靠,不保证数据一定到达。
相关推荐
Liuqy-0528 分钟前
IO模型与并发服务器
服务器·网络·select·多线程·epoll·并发服务器·io多路复用
梅孔立2 小时前
Docker 容器网络不通:Tomcat 无法解析 MySQL、Nginx 无法反代 Tomcat 的生产级排查与治理
网络·docker·tomcat
YWamy9 小时前
如何降低RTC SDK在复杂网络环境下的运行成本
网络·音视频·实时音视频
北京盛世宏博9 小时前
信创国产化智慧档案馆管库系统:十二防一体化管控平台落地笔记
网络·方案·温湿度·智慧档案馆建设
w-w0w-w10 小时前
SQL注入
网络·数据库·sql
一条泥憨鱼10 小时前
【计算机网络】短连接、长连接与连接池:从 TCP 握手到池化复用的完整链路
网络·数据库·网络协议·tcp/ip·计算机网络
北京盛世宏博10 小时前
数字孪生 3D 可视化实战:档案十防体系温湿度数据联动与告警定位实现
网络·档案八防·十防
蹊黎11 小时前
Linux 下用 C 语言实现进度条
linux·c语言·单片机
Lynne30911 小时前
EtherCAT网络中,多个节点如何配置才能互不干扰?
网络·网络配置·ethercat·工业网络
Yang961112 小时前
实验室里的多面手:鼎讯信通TM-150信号发生器技术拆解与实测思考
网络