UDP是传输层的一个协议,面向无连接,数据报的传输层协议。
特点:“无连接” “不可靠” “高效率”
没有TCP的确认机制,重传机制。
UDP信息包头只有8个字节,而我们的TCP的包头的有20个字节。
DNS(域名解析服务器)运行在UDP上,因为UDP的速度更快。
www.baidu.com ---> 域名
14.215.177.38
HTTP使用TCP而非UDP,因为对于基于文本数据的Web网页来说,可靠性更加重要。
在网络环境比较好的情况下,UDP的效率是比较高。
UDP协议会尽最大的努力去交付数据,但是不能够保证可靠交付,所以我们就需要再
应用层加一些保证可靠传输的“控制协议”。
3. 套接字选项(Socket Options)
每一个套接字在不同的协议层面(级别)上有不同的行为属性(选项),
有两个函数去设置/获取套接字的选项。
getsockopt:获取套接字的选项
setsockopt:设置套接字的选项
NAME
getsockopt, setsockopt - get and set options on sockets
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int getsockopt(int sockfd, int level, int optname,void *optval, socklen_t *optlen);
sockfd:要获取套接字的文件描述符
level:要获取的那个选项的“级别”
optname:要获取的那个选项的选项名“宏”
optval:指向一块空间。
用来保存获取的选项的值的。
如:SO_RCVBUF ---> int *
SO_SEDTIMED ---> struct timeval *
.....
optlen:指向一块空间 用来保存获取到的选项的值的数据长度的
返回值:成功返回0,失败返回-1,同时errno被设置。
int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);
int sockfd, int level, int optname
前三个参数跟getsockopt是一致的,
optval:指向要设置的选项值
optlen:要设置的选项值所占的空间的长度。
返回值:成功返回0,失败返回-1,同时errno被设置。
2. 设置套接字选项,允许地址和端口重用
optname:SO_REUSEADDR
SO_REUSEPORT
level:SOL_SOCKET
值的类型:int (1/0)
int on = 1;
int ret = setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void *)&on,sizeof(on));
if(ret == -1)
{
}
int ret = setsockopt(sock,SOL_SOCKET,SO_REUSEPORT,(void *)&on,sizeof(on));
if(ret == -1)
{
}
三、广播和组播(多播)
广播就是向局域网内部所有的主机通信,但是广播还是需要指定接受者的端口号的。
注意:
a. 只有传输层协议是UDP协议时,才支持广播功能
因为TCP是端对端,广播是一对多。
b. 广播地址
广播地址是专门用于同时向网络中所有的主机进行发送的一个地址。
子网内广播地址是:主机号全为1的IP地址就是广播地址。
例子:
Netmask:255.255.128.0 IP:192.168.31.56
广播地址:192.168.127.255
Netmask:255.255.192.0 IP:192.168.31.33
广播地址:192.168.63.255
全网广播地址:255.255.255.255
多播(组播)multicast
单播用于两个主机之间的端对端的通信
广播用于一个主机对整个局域网上的所有主机进行数据通信。
有时候,我们需要对一组特定的主机进行通信-->多播组号
也即是说,处于同一组的主机就能够接收到数据,而不在同一组的主机就接收不到数据
注意:
a. 多播也只有传输层协议为UDP时,才支持多播功能
b. 多播地址是IPv4的D类地址。
224.0.0.0 ~ 239.255.255.255
多播的编程流程:
多播同样的也分为服务器(多播发送)端和客户(多播接收)端.
服务器(多播发送)端:
1. 创建一个套接字-->AF_INET,SOCK_DGRAM,0
2. 通过sendto发送信息到一个多播组地址上去
多播组地址:D类IP地址+端口
3. 关闭套接字
服务器端不需要加入多播组,就可以直接向某个多播组发送数据,
而如果你要接收数据的话,就必须要加入多播组。
客户(多播接收)端:
1. 创建一个套接字-->AF_INET,SOCK_DGRAM,0
2. 加入一个多播组
3. 绑定一个地址
绑定多播组的地址
4. 接收多播组的数据
5. 也可以发送信息到多播组
6. 关闭套接字
代码实现-->加入一个多播组
加入多播组主要用到一个结构体:
<netinet/in.h>
struct ip_mreq
{
//多播组的地址(D类的IP地址)
struct in_addr imr_multiaddr;
//指定客户端主机加入组播使用哪张网卡的IP地址
struct in_addr imr_interface;
};
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr("224.10.10.1");
mreq.imr_interface.s_addr = inet_addr("192.168.31.95");
or
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
INADDR_ANY:让内核帮我们随便选一张网卡
int ret = setsockopt(sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,(void *)&mreq,sizeof(mreq));
只有加入多播组,你才可以从多播组中获取信息。
NTP:Network Time Protocol
UDP的服务器,这个服务器是用来是计算机时间同步化的一种服务器。
阿里云NTP服务器IP:182.92.12.11,端口号:123