一、是什么
UDP(User Datagram Protocol,用户数据报协议)是一种简单的、无连接的传输层协议,用于在网络中传输数据。
与 TCP 不同,UDP 不提供可靠性、顺序性和流量控制,但它具有低延迟和高效的特点,适合对实时性要求较高的应用。
UDP 是一种无连接协议,客户端和服务器之间不需要建立连接即可发送数据。它的核心功能是快速传输数据包。
二. UDP 数据包结构
UDP 数据包由以下部分组成:
- 源端口:发送方的端口号。
- 目的端口:接收方的端口号。
- 长度:数据包的总长度(包括头部和数据)。
- 校验和:用于检测数据包是否损坏(可选)。
- 数据:实际传输的数据
三、编程
1.socket与TCP相同
2.socket之后直接收发
1)发送
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
功能:
sendto 将数据发送到指定的地址中,通过sockfd
参数:
@sockfd --- 表示socket对应的fd
@buf --- 存放数据的一块内存空间
@len --- 表示要发送的字节数
@flags --- 发送的标志 MSG_DONWAIT //非阻塞 --- 不在等 0 ---默认方式
@dest_addr --- 目标地址 --- 代表要发送到的目的地址
@addrlen --- 代表 目标地址数据的长度 sizeof(dest_addr)
返回值:
成功 返回发送出去的字节数 失败 -1 && errno被设置
2)接收
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
功能:
从socket中接收消息
参数:
@sockfd --- 表示socket对应的fd
@buf --- 存放数据的一块内存空间
@len --- 表示打算读取的字节数
@flags --- 读取的标志 MSG_DONWAIT //非阻塞 --- 不在等
@src_addr --- 表示数据的源地址
@addrlen --- 源地址大小
值结果参数ocklen_t addrlen = sizeof(src_addr);
返回值:
成功 返回读取到的字节数 失败 -1 && errno被设置
客户端:
cpp
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <strings.h>
#include <string.h>
#include <arpa/inet.h>
int main(int argc, const char *argv[])
{
int clifd = socket(AF_INET,SOCK_DGRAM,0);
if (clifd < 0)
{
perror("socket fail");
return -1;
}
//bind
//sendto 鍑芥暟
char buf[1024] = "hello udp!\n";
struct sockaddr_in seraddr;
bzero(&seraddr,sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
seraddr.sin_port = htons(50000);
sendto(clifd,buf,strlen(buf)+1,0,(const struct sockaddr *)&seraddr,sizeof(seraddr));
return 0;
}
服务器:
cpp
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <strings.h>
#include <arpa/inet.h>
int main(int argc, const char *argv[])
{
int serfd = socket(AF_INET,SOCK_DGRAM,0);
if (serfd < 0)
{
perror("socket fail");
return -1;
}
//bind
struct sockaddr_in seraddr;
bzero(&seraddr,sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_addr.s_addr = INADDR_ANY;
seraddr.sin_port = htons(50000);
if (bind(serfd,(const struct sockaddr*)&seraddr,sizeof(seraddr)) < 0)
{
perror("bind fail");
return -1;
}
//recvfrom 鍑芥暟
char buf[1024];
struct sockaddr_in srcaddr;
socklen_t len = sizeof(srcaddr);
recvfrom(serfd,buf,sizeof(buf),0,(struct sockaddr*)&srcaddr,&len);
printf("-------------------\n");
printf("ip = %s\n",inet_ntoa(srcaddr.sin_addr));
printf("port = %d\n",ntohs(srcaddr.sin_port));
printf("buf = %s\n",buf);
return 0;
}