常见端口
在TCP/IP协议中, 用 “源IP”, “源端口号”, “目的IP”, “目的端口号”, “协议号” 这样一个五元组来标识一个通信(可以通过netstat -n查看);
- 0 - 1023: 知名端口号, HTTP, FTP, SSH等这些广为使用的应用层协议, 他们的端口号都是固定的
- 1024 - 65535: 操作系统动态分配的端口号. 客户端程序的端口号, 就是由操作系统从这个范围分配的。
常用的服务器都是固定端口号的。ssh服务器, 使用22端口,ftp服务器, 使用21端口,telnet服务器, 使用23端口,http服务器, 使用80端口,https服务器, 使用443。
在Linux中可以通过 cat /etc/services 常看知名服务器的端口。
netstat命令
netstat是一个用来查看网络状态的重要工具。
用法 : netstat -选项
- n 拒绝显示别名,能显示数字的全部转化成数字
- l 仅列出有在 Listen (监听) 的服务状态
- p 显示建立相关链接的程序名
- t (tcp)仅显示tcp相关选项
- u (udp)仅显示udp相关选项
- a (all)显示所有选项,默认不显示LISTEN相关
另外在LInux中可以通过pidof [进程名] 的方式来查看进程ID。
UDP协议
UDP协议是传输层的协议,是在应用层之下的。它在Linux内核中,我们可以通过系统调用接口,来实现UDP的网络编程。
UDP协议的格式
UDP的报头非常简单,存在16位源端口和16为目的端口,16位UDP长度, 表示整个数据报(UDP首部+UDP数据)的最大长度,如果校验和出错, 就会直接丢弃。
UDP协议首部中有一个16位的最大长度. 也就是说一个UDP能传输的数据最大长度是64K(包含UDP首部).所以如果数据超过了64K,就需要进行多次发送了。
UDP如何实现报头和有效载荷分离呢?
UDP采用的是固定报头的做法,报头的大小永远为8字节,16位的UDP长度减去8字节就是有效载荷的长度。这样OS就可以知道是否把数据收全了。
UDP如何将有效载荷向上进行交付呢?
UDP可以通过目的端口来进行向上交付。
所谓的报头在内核中其实就是结构化字段。
所以UDP在发送报文前只需要把把头的结构化字段填好,然后防止报文的前面就可以像服务器进行请求了,但是不管是服务器还是客服端,都一定存在大量的UDP报文,所以OS也一定要对这么多的报文进行管理,所以OS也会存在对报文描述的结构体,报文本质就是数据,所以就是一段缓冲区,所以描述报文的结构体里面一定会存在指针。
所以OS对报文的管理就成了对这个链表的增删查改。
当数据放在缓冲区之后,只需要在数据的前面把报头加上就可以直接进行发送了。当服务器收到后,因为报头的大小是固定的,所以很容易对报文进行解包。
应用层交给UDP多长的报文, UDP原样发送, 既不会拆分, 也不会合并,这就叫做面向数据报。
UDP没有真正意义上的 发送缓冲区,当我们调用sendto之后,OS会把我们的数据拷贝到内核形成一个报文,然后添加报头进行发送,但是UDP拥有接受缓冲区,但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致; 如果缓冲区满了, 再到达的UDP数据就会被丢弃;接受缓冲区可以理解为一个struct sk_buff的一个队列。
基于UDP的应用层协议
- NFS: 网络文件系统
- TFTP: 简单文件传输协议
- DHCP: 动态主机配置协议
- BOOTP: 启动协议(用于无盘设备启动)
- DNS: 域名解析协议