UDP
# 前序
UDP(用户数据报协议)没有连接的,是面向数据报的,是不可靠
# 套接字
就是IP地址+端口号
IP地址:4字节
端口号:2字节,也就是说范围是0~65535
IP地址的理解:
端口号的理解:
-
端口号就是用来告诉操作系统要对于那一个进程进行操作,也就是说端口号就是用来标识一个进程
-
一个端口号只可被一个进程所占用,但是一个进程可以拥有多个端口号,也就是进程和端口号是一对多的关系
-
当我们写一个程序使用端口号的时候,要避开这些知名端口号
【问题】
-
一个进程是否可以bind多个端口号呢?
-
一个端口号是否可以被多个进程bind?
-
多个进程可以监听同一个端口号吗?
所以套接字就可以准确的标识一台主机上的一个进程,从而完成计算机之间的通信
计算机之间的通信:
# 网络字节序转换
对于数据在网络中传输的时候有着自己遵循的传输规则大端传输
对于主机上的数据的传输序列有着两种:
所以对于主机上的数据传输的时候传输到网络上的时候有可能导致数据错误(例如主机上是小端的时候,所以需要进行转换)
转换函数:
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16 hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
h:表示主机host name
n:表示网络network
l:表示4字节long
s:表示2字节short
# 地址转换函数
-
字符串转化为in_addr
-
in_addr转化为字符串
# UDP协议
UDP协议端格式
插图:UDP协议端格式
-
16为UDP长度,表示整个数据报(UDP首部+UDP数据)的最大长度(64KB)
-
检验和:如果校验和出错,就会直接丢弃(检验的是把首部和数据部分一起都检验)
-
源端口号:在对方回信是选用,不需要时可用全0
-
目的端口号:在终点交付报时必须要用到
-
长度:UDP用户数据报的长度,其最小值是8(仅有首部)
UDP的特点
-
无连接:直到对端的IP和端口号就直接进行传输,不需要建立连接
-
不可靠:没有确认机制,没有重传机制;因为没有网络故障该段无法发送到对方,UDP协议层也不会给应用层返回任何错误信息
-
面向数据报:不能够灵活的控制读写数据的次数和数量
-
控制选项较少,数据传输过程中延迟小,数据传输效率高
面向数据报
UDP的缓存区
UDP的Socket既能读,也能写,全双工
UDP的使用注意事项
-
UDP协议首部中有一个16位的最大长度,也就是说一个UDP能传输的数据的最大长度是64K(包含UDP首部)。但是64K在当今的互联网环境下,是一个非常小的数字。如果我们需要传输的数据超过64K,就需要应用层手动的分包,多次发送,并在接收端拼装
-
UDP首部中校验和的计算方法有些特殊。在计算校验和时,要在UDP用户数据报之前增加12个字节的伪首部
-
伪首部既不向下传输也不想上递送,而仅仅是为了计算校验和
-
与IP数据报的校验和只检验IP数据报的首部不同,UDP的校验和是把首部和数据部分一起都检验
伪首部:
插图:伪首部
基于UDP的应用层的协议
-
NFS:网络文件系统
-
TFTP:简单文件传输文件协议
-
DHCP:动态主机配置协议
-
DNS:域名解析协议
面试题:用UDP实现可靠传输?
参考TCP的可靠性机制,在应用层实现类似的逻辑
-
引用序列号,保证数据顺序
-
引入确认应答,确保对端收到了数据
-
引入超时重传,如果隔一段时间没有应答,就重发数据
1. 对于socket函数的使用
1.1 函数原型
int socket(int domain, int type, int protocol);
domain: 领域
AF_INET:IPV4
AF_INET6:IPV6
type: 类型
SOCK_STREAM
SOCK_DGARM
protocol: 协议
1.2 函数的作用
在通信领域中创建一个未被绑定的套接字,并且返回一个文件描述符,可以在以后对套接字进行操作的函数调用中使用
2. 对于bind函数的使用
2.1 函数原型
int bind(int socket, const struct sockaddr* address, socklen_t address_len);
2.2. 函数的作用
该函数采用先前创建好的套接字来对于IP地址以及端口号进行绑定,也就是表示该套接字可以标识出在一个网络中一台确定的主机并且主机中的进程
3. 对于recvfrom函数的使用
3.1 函数原型
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:接收的消息的长度
flags:类型
address:空指针或者存储发送信息的sockaddr结构
addless_len:指定地址参数指向的sockaddr结构的长度
3.2 函数的作用
3.2 函数的作用
用来接收从socket套接字发送来的消息。该套接字的sockaddr结构也知道
4. 对于sendto函数的使用
4.1 函数原型
ssize_t recvfrom(int socket, const void* message, size_t length,
int flags, const struct sockaddr* dest_addr,
socklen_t* dest_len);
4.2 函数的作用
该函数是socket套接字从dest_addr出接收消息
5. 扩展知识
5.1 netstat
netstat是一个用来监控TCP/IP网络非重要工具
语法:netstat [选项]
功能:查看网络状态
选项:
-
-a,显示所有连线的Socket
-
-c,持续列出网络状态
-
-n,直接使用ip地址,而不通过域名服务器,也就是显示为数字
-
-l,显示监控中的服务器的Socket,仅列出监听(Listen)状态下的Socket
-
-p,显示正在使用Socket的程序的识别码和名称(PID/Program name)
-
-t,显示TCP传输协议的连线状况
-
-u,显示UDP传输协议的连线状况
-
-v,显示指令执行过程
-
-V,显示版本信息
-
-x,显示UNIX传输协议的连线状况
-
-s,显示网络工作信息统计表
-
-h,在线帮助
5.2 pidof
查看服务器进程id是非常方面
语法:pisdof [进程名]
功能:通过进程名,查看进程id
5.3 scp命令
基于ssh登录进行的网络安全的远程文件拷贝命令
例:要将自己当前路径下的clinet文件发送到主机IP为192.168.153.140的home目录下
scp ./clinet root@192.168.153.140:/home
5.4 关于防火墙的命令
-
启动:systemctl start firewalld
-
关闭:systemctl stop firewalld
-
查看状态:systemctl status firewalld
-
开机禁用:systemctl disable firewalld
-
开机启用:systemctl enable firewalld
# 对于UDP书写服务器的思路
由于UDP是无连接的,所以对于两个处于同一局域网下计算机的进程之间通信,所以是不需要两台计算机之间的进程进行连接的,对于UDP使用的接口是需要包含知道从哪里接收消息的,要发送消息到哪里的。
-
实现本地通信
-
实现处于同一局域网下的不同主机间进行通信
# 对于UDP服务器要注意的问题
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)