UDP 协议通信程序的编写
UDP 协议:无连接、不可靠、基于数据报传输
两端通信流程:
套接字相关接口介绍
#include <sys/socket.h> 头文件
一、 创建套接字
int socket(int domain, int type, int protocol);
(1) domain:地址域类型(域间通信、ipv4通信、ipv6通信… 不同通信有不同的地址结构)
(2) type:套接字类型
SOCK_STREAM:流式套接字,提供字节流传输,默认协议是 TCP 协议
SOCK_DGRAM:数据报套接字,提供的是数据报传输,默认协议是 UDP 协议
(3) protocol:协议类型,默认使用 0,表示使用套接字类型对应的默认协议
IPPROTO_TCP:值为 6
IPPROTO_UDP:值为 17
返回值:成功返回一个套接字描述符,失败返回 -1
二、为套接字绑定地址信息
int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
(1) sockfd:socket 返回的套接字描述符
(2) my_addr:要绑定的地址信息
但是不同地址域类型具有不同的地址结构
ipv4 地址域类型 2B;端口号 2B;IP地址 4B
ipv6 地址域类型 2B;端口号 4B;IP地址 4B
(3) addrlen:绑定地址信息的长度
返回值:成功返回 0 ,失败返回 -1
三、发送数据
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
(1) sockfd:socket 返回的套接字描述符
(2) buf:要发送的数据空间起始地址
(3) len:要发送的数据长度,从 buf 地址开始,发送 len 长度的数据
(4) flags:默认 0-阻塞发送(发送缓冲区数据满了则等待)
(5) dest_addr:对端地址信息,描述数据要发送给谁(设置地址信息)
(6) addrlen:对端地址信息长度
返回值:成功返回实际发送数据字节长度,失败返回 -1
四、接收数据
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
(1) sockfd:socket 返回的套接字描述符
(2) buf:空间起始位置,接收到的数据存放在 buf 空间中
(3) len:想要接收到的数据长度
(4) flags:默认 0-阻塞接收(socket 接收缓冲区中没有数据则阻塞,直到有数据)
(5) src_addr:接收数据的同时,需要知道数据是谁发的,(获取地址信息)输出参数,用于返回对端地址信息
(6) addrlen:地址信息长度,输入输出参数,表示想要接收的地址信息长度以及实际得到的地址信息长度
返回值:成功返回实际接收到的数据长度,失败返回 -1
五、关闭套接字,释放资源
int close(int fd);
字节序相关接口
注意 32 位数据转换接口与 16 位数据转换接口不可混用
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
主机字节序到网络字节序的转换
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
网络字节序到主机字节序的转换
示例说明:
IP 地址转换接口
in_addr_t inet_addr(const char *cp); 将点分十进制IP地址转换为网络字节序整型IP地址
const char *inet_ntoa(struct in_addr in); 将网络字节序整型IP地址转换为点分十进制IP地址
inet_ntoa 接口,若返回的是一个局部变量(函数退出就会释放),这个函数返回的是静态变量地址
测试代码:
服务端:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 #include<unistd.h>
5 #include <arpa/inet.h> //字节序转换接口头文件
6 #include <sys/socket.h> //套接字接口头文件
7 #include <netinet/in.h> //地址结构类型以及协议类型宏头文件
8
9 int main(int argc,char* argv[])
10 {
11 if(argc!=3){
12 printf("./udp_ser 192.168.2.2 9000\n");
13 return -1;
14 }
15 uint16_t port=atoi(argv[2]); //端口信息,uint16 属于 ipv4 数据类型----包含有2字节16位数据 ,atoi 将字符串转换为整数
16 char* ip=argv[1] ; //ip 地址信息
17
18 //1、创建套接字
19 //int socket(int domain, int type, int protocol);
20 int sockfd=socket(AF_INET ,SOCK_DGRAM,IPPROTO_UDP);
21 //AF_INET 代表的是 ipv4 地址域类型,SOCK_DGRAM 表示数据报套接字-UDP,IPPROTO_UDP 表示 UDP 协议类型
22
23 if(sockfd<0){
24 perror("socket error!\n");
25 return -1;
26 }
27
28
29 //2、为套接字绑定地址信息
30 //int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
31
32 str