UDP协议服务器
UDP协议概念
UDP协议是在整个网络分层的传输层的协议,具有以下特性
1.无连接
2.不可靠传输
3.面向数据报
关于特性这里不做过多阐述
网络字节序
首先网络数据流采用大端字节序,即低地址高字节。
网络中先发出去的数据是低地址,后发出去的数据是高地址
而为什么是大端字节序存储呢?
原因如下:
我们都知道,网络是分层的,数据在各个层面进行传输时是需要添加报头的。而报头是添加在数据之后的,所以是存储在低地址处。
即
由于网络中先发出去的是低地址的数据,等同于先发出去的数据是报头,后发出去的是真正的数据,而接收方是先接收报头,再接收数据,先接收报头并解析,可以通过报头得到数据的属性,进而针对性的接收数据。这样做可以节省时间,提高数据在网络层面中的传输效率。
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
h:表示主机,n表示网络 ,l代表32位长整数,s表示16位短整数
htons 16位短整数主机字节序转网络字节序
UDP服务器的常见API
/创建 socket 文件描述符(客户端+服务端)
int socket(int domain, int type, int protocol);
damain:IPV4通信,AF_INET
type:类型,SOCK_DGRAM
protocol:选择0即可
返回值:成功返回一个文件描述符,失败返回-1
绑定端口号 ( 服务器)
int bind(int socket, const struct sockaddr *address,socklen_t address_len);
socket:socket得到的文件描述符
address:struct sockaddr *的一个结构体,一般需要从struct sockaddr_in 结构体强转而来
address_len:address结构体的大小
返回值:成功返回0,失败返回-1
struct sockaddr_in 结构体
里面有三个成员,分别是
sin_family,协议家族
sin_port 端口号
sin_addr,网络地址(IP) 是一个结构体,里面的成员只有一个,为s_addr
在bind的时候需要先对struct sockaddr_in结构体进行初始化
sin_family: AF_INET
sin_port:端口号,需要通过主机转网络函数进行转换 htons,htonl
sin_addr.s_addr: IP,需要通过inet_addr函数进行转换
in_addr_t inet_addr(const char *cp);
接收消息(客户端+服务端)
ssize_t recvfrom(int socket, void *restrict buffer, size_t length,
int flags, struct sockaddr *restrict address,
socklen_t *restrict address_len);
socket:文件描述符
buffer:写到哪(存放数据的位置)
length:希望读取的长度
flag:设为0即可
address:结构体,详见bind
len:结构体的大小
返回值:实际读取的长度
发送数据(客户端+服务端)
ssize_t sendto(int socket, const void *message, size_t length,
int flags, const struct sockaddr *dest_addr,
socklen_t dest_len);
socket: