《Linux网络开发必学教程》15_UDP 数据收发实战

问题:如何使用 UDP 进行数据收发?
再论 UDP 协议
  • UDP 是无连接的(不可靠的,无应答消息,数据包无序号标识)
  • UDP 是面向数据包的,对应用层数据既不合并也不拆分(保留数据包边界)
  • UDP 没有拥塞控制,网络出现的拥塞不会使源主机的发送速率降低
  • UDP 支持一对一,一对多,多对一和多对多的交互通信
  • UDP 消息头开销小,只有 8 个字节(TCP 消息头共 20 个字节)
《Linux网络开发必学教程》15_UDP 数据收发实战
文章图片

UDP 和 IP 的区别
UDP 是建立于 IP 之上的数据传输协议
  • IP 负责将 UDP 数据包从源主机传输到目标主机
  • UDP 则将应用层数据投递到目标 socket (端口号)
UDP 几乎完整 “继承” 了 IP 传输的特性
  • 通讯两端无交互,无流控,无超时重发,不具备可靠性
UDP 收发数据
#include "sys/socket.h"ssize_t send(int sock,// socket 文件描述符 void *buf,// 需要发送的数据 size_t nbytes,// 需要发送的数据量 int flags,// 发送选项 struct sockaddr *to,// 接收地址信息 socklen_t addrlen); // to 参数长度ssize_t recvfrom(int sock,// socket 文件描述符 void *buf,// 保存接收数据的地址 size_t nbytes,// 可接收的最大数据量 int flags,// 接收选项 struct sockaddr *from, // 接收地址信息 socklen_t *addrlen); // 指向保存 from 参数长度的变量地址

UDP 编程模式 【《Linux网络开发必学教程》15_UDP 数据收发实战】《Linux网络开发必学教程》15_UDP 数据收发实战
文章图片

编程实验:UDP 数据收发
client.c
#include #include #include #include #include #include #include int main() { int sock = 0; struct sockaddr_in addr = {0}; struct sockaddr_in remote = {0}; socklen_t len = 0; char buf[128] = {0}; char input[32] = {0}; int r = 0; sock = socket(PF_INET, SOCK_DGRAM, 0); if (sock == -1) { printf("socket error\n"); return -1; }addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(7777); if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) { printf("udp bind error\n"); return -1; }remote.sin_family = AF_INET; remote.sin_addr.s_addr = inet_addr("127.0.0.1"); remote.sin_port = htons(8888); while (1) { printf("Input: "); scanf("%s", input); len = sizeof(remote); sendto(sock, input, strlen(input), 0, (struct sockaddr*)&remote, len); r = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr*)&remote, &len); if (r > 0) { buf[r] = 0; printf("Recvfrom %s\n", buf); } else { break; } }close(sock); return 0; }

server.c
#include #include #include #include #include #include #include int main() { int server = 0; struct sockaddr_in saddr = {0}; int client = 0; struct sockaddr_in remote = {0}; socklen_t asize = 0; int len = 0; char buf[32] = {0}; int r = 0; server = socket(PF_INET, SOCK_DGRAM, 0); if (server == -1) { printf("server socket error"); return -1; }saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); saddr.sin_port = htons(8888); if (bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) { printf("udp server bind error\n"); return -1; }printf("udp server start sucess\n"); while (1) { len = sizeof(remote); r = recvfrom(server, buf, sizeof(buf), 0, (struct sockaddr*)&remote, &len); buf[r] = 0; printf("r = %d\n", r); printf("buf = %s\n", buf); printf("remote ip = %s\n", inet_ntoa(remote.sin_addr)); printf("remote port = %d\n", ntohs(remote.sin_port)); sendto(server, buf, r, 0, (struct sockaddr*)&remote, len); }close(server); return 0; }

输出:
server: udp server start sucess r = 5 buf = hello remote ip = 127.0.0.1 remote port = 7777---client: Input: hello Recvfrom hello

思考:如何进行一对多的 UDP 数据收发?

    推荐阅读