目录
1.再谈端口
1.1 五元组
端口号表示了一个主机上进行通信的不同的应用程序;在Tcp/IP协议中,用源IP,源端口号,目的IP和目的端口号以及协议号来标识唯一的通信(可以通过netstat-n来进行查看)。
1.2 端口号范围划分
0-1023:知名端口号,HTTP,FIP,SSH等这些广为使用的应用层协议,他们的端口号都是固定的。
1024-65535:操作系统分配的端口号,客户端程序的端口号,就是由操作系统从这个范围分配的。人们约定了一些服务器只能使用以下端口:
ssh:22端口
ftp:21端口
telnet:23端口
http:80端口
https:443端口
使用cat /etc/services可以查看指明端口号。
注意:一个进程可以bind多个端口号,但是一个端口号不能被多个进程bind。
1.3 两个指令
1.3.1 netstat
netstat是一个用来查看网络状态的重要工具。
-n:拒绝显示别名,能显示数字的全部转化为数字。
-l:仅列出在有Listen状态下的服务状态。
-p:显示建立相关链接的程序名。
-t:仅显示tcp的相关选项。
-u:仅显示udp的相关选项。
-a:显示所有选项,默认不显示Listen相关的。
1.3.2 pidof
pidof+进程名可以直接查看进程的pid。
2.UDP协议
2.1 协议整体格式
udp与tcp是传输层协议,要了解这两个协议组成,我们需要知道协议的传递原理,传递无非包含两两个内容,即
如何做到封装和解包(协议报头的大小)
如何向上交付(如何找到要交付的上层程序)。
其中udp协议中的报头是定长的8个字节,16位udp长度就是整个udp的长度,两者相减就可以得到数据的大小。我们可以根据定长的报头长度来进行封装和解包。
同时,udp协议中有16位的目的端口号,它可以找到上层的某个进程,从而将报文进行向上交付。Linux内核是使用C语言来写的,报头是使用位段来定义的,类似如下结构:
struct udp_hdr
{
uint32_t src_port:16;
uint32_t dst_port:16;
uint32_t total:16;
uint32_t check:16;
}
可以将报头设为一个指针结构来进行插入和删除。
2.2 udp特点
udp的通信过程类似于寄信。
无链接:知道对端的IP和端口号就可以直接进行传输,不需要建立链接。
不可靠:没有确认机制,没有重传机制;如果因为网络故障该段无法发送到对方,udp协议层也不会给应用层返回任何错误信息。
面向数据报:不能够灵活的控制读写数据的次数和数量。
面向数据报指的是应用层传给udp多长的报文,udp会原样发送,既不会拆分也不会合并;比如udp传输100个字节的数据:
如果发送端调用一次sendto,则发送100个字节,那么接收端也必须调用对应的一次recvfrom,接收100个字节;而不能循环调用十次recvfrom,每次接收10个字节。
2.3 udo缓冲区
udp没有真正意义上的发送缓冲区,调用sendto就会直接交给内核,再由内核将数据传给网络协议进行后续的传输动作;
udp具有接收缓冲区,但是这个接收缓冲区就不能保证收到的udp报的顺序和发送udp报的顺序一致,如果缓冲区满了,再到达的udp数据就会被丢弃;
udp是全双工的,即可以在sendto的同时调用recvfrom,应用层我们调用的recv,read,write,sendto等函数,与其说是收发函数不如说是拷贝函数,其实都是在缓冲区中完成拷贝。