1、UDP简介
UDP(User Datagram Protocol)用户数据报协议是一种非面向连接的协议,这种协议并不能保证
我们的网络程序的连接是可靠的,而TCP是面向连接的协议,提供可靠服务。但是相对于TCP而言,UDP实时性较好,适用于高速传输和实时性要求较高的通信中。
2、实现过程
UDP服务器端实现步骤:
1、创建socket,选用SOCK_DGRAM(UDP)
2、bind绑定ip地址和socket
3、使用recvfrom()函数接收客户端数据
(4、使用sendto函数发送数据)
UDP客户端实现步骤:
1、创建socket,选用SOCK_DGRAM(UDP)
2、定义sockaddr_in 结构体变量并初始化
3、使用recvfrom()函数接收客户端数据
相关函数API介绍
int socket(int domain, int type, int protocol);
参数:
domain:域。
AF_INET/PF_INET: 网际协议
AF_UNIX/PF_UNIX:本地协议,可写成AF_LOCAL/PF_LOCAL
type:类型
SOCK_STREAM:流式套接字
SOCK_DGRAM:数据报套接字
protocol:协议
一般为0
返回值:
成功:待连接套接字;
失败:-1
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数:
sockfd:待连接套接字
addr:包含本地地址(IP+PORT)的通用地址结构体的指针
addrlen:地址结构体大小
返回值:
成功:0;
失败:-1
备注,通用地址结构体的定义:
struct sockaddr
{
sa_family_t sa_family;
char sa_data[14];
};
特殊地址结构体 —— IPv4地址结构体:
struct sockaddr_in
{
u_short sin_family; // 地址族
u_short sin_port; // 端口
struct in_addr sin_addr; // IPV4地址
char sin_zero[8];
};
struct in_addr
{
in_addr_t s_addr; // 无符号32位网络地址
};
特殊地址结构体 —— IPv6地址结构体:
struct sockaddr_in6
{
u_short sin6_family; // 地址族
__be16 sin6_port; // 端口
__be32 sin6_flowinfo; // 流信息
struct in6_addr sin6_addr; // IPv6地址
__u32 sin6_scope_id;
};
特殊地址结构体 ——UNIX域地址结构体:
struct sockaddr_un
{
u_short sun_family; // 地址族
char sun_path[108]; // 套接字文件路径
};
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
接口声明:从UDP套接字接收数据
参数:
sockfd:UDP套接字
buf:储存数据缓冲区
len:缓冲区大小
flags:接收标志,与函数send的flags完全一致
src_addr:对端网络地址
addrlen:地址长度
返回值:
成功:已接收字节数
失败:-1
2.1服务器代码
/*
基于UDP实现的服务器
author:zx
date:2023-3-10
创建服务步骤:
1、创建socket,选用SOCK_DGRAM(UDP)
2、bind绑定ip地址和socket
3、使用recvfrom()函数接收客户端数据
*/
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
int main()
{
int sockfd;
int retval;
if(sockfd == -1)
{
printf("sock error\n");
return -1;
}
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr =htonl(INADDR_ANY);//任意地址
serverAddr.sin_port = htons(6565);
retval = bind(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
if(retval < 0)
{
printf("bind error\n");
return -1;
}
{
printf("[UDP server]recv form client:%s\n", buf);
}
else
{
printf("[UDP server] recv error!\n");
break;
}
}
close(sockfd);
return 0;
}
2.2客户端代码
/*
基于UDP实现的客户端
author:zx
date:2023-3-10
创建服务步骤:
1、创建socket,选用SOCK_DGRAM(UDP)
2、定义sockaddr_in 结构体变量并初始化
3、使用recvfrom()函数接收客户端数据
*/
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
int main()
{
int sockfd;
int retval;
struct sockaddr_in clientAddr;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);//UDP
if(sockfd == -1)
{
printf("sock error\n");
return -1;
}
clientAddr.sin_family = AF_INET;
clientAddr.sin_addr.s_addr = htonl(INADDR_ANY);
clientAddr.sin_port = htons(6565);
char buf[1024] = "hello udp server";
socklen_t len = sizeof(clientAddr);
int count = 0;
while(1)
{
sprintf(buf, "hello udp server,count:%d", count++);
retval = sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&clientAddr, len);
if(retval > 0)
{
printf("[UDP client]send to server:%s\n", buf);
}
else
{
printf("[UDP client] send error!\n");
break;
}
sleep(2);
}
close(sockfd);
return 0;
}
3、运行结果
客户端
服务器端