传输层负责不同主机上进程间的数据传输,因为传输层的协议中包含主要信息就是端口,典型协议就是TCP/UDP协议
端口号
端口号范围划分:0-1023:HTTP、FTP、SSH等应用层协议,我们无法绑定,HTTP协议端口号不能修改。
1024-65535:操作系统动态分配的端口号,客户端程序的端口号,都是操作系统从这个范围分配的。
一些知名端口号:ssh服务器:22端口;ftp服务器:21端口;telnet服务器:23端口;http服务器:80端口;https服务器:443端口;执行cat /etc/services可以查看这些知名端口号;
一个进程可以绑定多个端口号,一个端口号不能被多个进程绑定;
- netstat命令
用来查看网络状态的命令,选项有n表示拒绝显示别名,能显示数字的全部转化为数字;l表示列出有在listen的服务状态;p表示显示建立相关链接的程序名;t表示仅显示tcp相关选项;u表示仅显示udp相关选项;a表示显示所有选项,默认不显示listen相关 - pidof命令
查看服务器的进程id比较方便,用法是:pidof 进程名
UDP协议
- UDP协议端格式
如图:
报头包括四部分:16为位源端口号、16位目的端口号、16位UDP长度、16位UDP检验和;报头是用位段进行定义的,例如:
//带一个报头
struct udp
{
unsigned int src_length:16;
unsigned int dst_length:16;
unsigned int length:16;
unsigned int check:16;
};
int main()
{
char msg[]="other data";
udp head={1234,4321,xxx,yyy};//报头
char* mem=malloc(sizeof(udp)+sizeof(msg));
//封装
}
这样就添加了一个报头,然后封装就是加报头和有效载荷。
udp分离报头和有效载荷定长短;分用是采用目的端口号。
- UDP的特点
udp发送数据只要将数据发送出去就不管了,至于接收端有没有收到,udp本身并不保障;
特点:
(1)无连接:知道对端的ip和端口号就直接进行传输,不需要建立连接
(2)不可靠:不保证数据安全有序的到达对端;
(3)面向数据报:限制传输最大大小的一种传输方式; - 注意
应用层的数据过大,需要程序员在应用层进行分包操作,将大数据分割成小的数据段,逐个发送,因为udp不保证数据有序到达,分包之后,程序员需要在应用层进行包序管理;
udp报头中定义了数据报长度,因此数据不能向上层交付半条数据或者多条数据,必须进行一整条交付,因此上层定义的接收buffer就需要给足够大; - UDP的缓冲区
UDP没有真正的缓冲区,调用sendto直接交给内核,由内核将数据传给网络层协议进行后续的传输动作;UDP具有接收缓冲区,但是这个接收缓冲区不能保证收到的udp报的顺序和发送udp报的顺序一致,如果缓冲区满了,再到达的udp数据就会被丢弃。
udp的socket既能读,也能写,是全双工的。
TCP协议(重要)
- TCP协议段格式
如图:
1、源、目的端口号表示数据从哪里来,到哪里去;
2、通过自描述字段(4位首部长度)来将报头和有效载荷分离;
3、32位序号和确认序号:用来实现包序管理和确认应答机制;
4、4位TCP报头长度表示该TCP头部有多少个32位bit,所以TCP头部最大长度是15*4=60;
5、6位标志位:
(1)URG:紧急指针是否有效,即此标志用于将输入数据标识为“紧急”,这样的进入段不必等待直到先前段被接收端消耗,而是直接发送并且立即处理;
例如在数据传输流中,主机正在向远程机器运行的应用程序发送数据,可以使用紧急指针;如果出现问题,主机需要终止数据传输,并在另一端停止数据处理,在正常情况下,中止信号将在远程机器发送和排队,直到所有先前发送的数据都被处理,但是我们的这种情况需要立即处理,需要紧急指针。
(2)ACK:确认号是否有效,ACK设置为1表示确认报文,设置为0表示不是确认报文,会提取确认序号,确认号只有在该位设置为1的时候生效;
(3)PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走(让对方尽快将数据处理好继续恢复数据发送端)
(4)RST:对方要求重新建立连接,用来复位那些产生错误的连接,也被用来拒绝错误和非法的数据报,把携带RST标识的称为复位报文段(如果要向主机发送数据报以建立连接,并且没有这样的服务等待在远程主机上回答,则主机自动拒绝你的请求,向你发送回复RST标志置1,这表示远程主机已重置连接)
(5)SYN:请求建立连接,设为1标识连接,把