套接字缓冲区相关
套接字缓冲区相关
书里面讲了三种方式(TCP,UDP,SCTP)的发送相关,但是原理基本是相同的,只是根据不同协议的特点有些变化.下面
以TCP为例,试着描述一下这个过程.
TCP缓冲区
每一个TCP套接字都有一个发送缓冲区,这个缓冲区是在内核中的.当我们调用write将数据写入套接字的时候,数据被传入
内核,放入套接字发送缓冲区(大小可以由SO_SNDBUF来设定).如果缓冲区已满,那么write函数将被阻塞,进程被投入睡眠状态.
直到数据全部被传入内核的套接字缓冲区中.需要注意的是,当write返回的时候并不代表对端已经收到了这些数据,只是说明这些
数据被写到了内核中的缓冲区里面.
当数据到达内核中以后,内核中的TCP程序会对其进行一次加工,将数据以MSS(maximum segment size)大小分块,并给每个数据块
安上一个TCP首部,随后发给IP程序.
IP程序可能会对数据进行进一步的分片,取决于MSS的大小.有的系统在实现中使用了路径MTU发现机制,会尽量减少分片的情况.通用的
做法就是给数据包加上IP头,按照其目的IP地址查找路由表确定网络接口,然后传递给数据链路层.
数据链路层中会维护一个队列,如果队列已满,则会沿协议栈返回一个错误,最终由TCP捕获这个错误,并重传该数据.
TCP缓冲区一个很重要的问题就是何时从套接字缓冲区中将已发送的数据丢弃.我们知道TCP是一个可靠的传输协议,所以TCP实现了关于确认数据
到达的相关机制,即当对端确认数据到达的ack返回时,则认定我们发送的数据已经被对方接受.此时内核中的套接字缓冲区才会将数据删除.在确认的
ack到达之前,内核的套接字缓冲区中会为数据维护一个副本,防止数据由于损坏或者丢失造成重传的时候内核已经将其删除了.
UDP缓冲区
UDP套接字的缓冲机制就不在详述,因为UDP是一个不可靠协议,所以它并不会维护一个真正的套接字缓冲区,而是直接沿协议栈向下传递,被复制到某种
格式的内核缓冲区当中.但是如果UDP打算传送一个大于"缓冲区大小"(即SO_SNDBUF的大小)的数据报时,则会返回一个EMSGSIZE的错误.它经过内核中
的UDP和IP程序,并被发送到数据链路层的缓冲队列当中,如果队列已满则返回一个ENOBUFS的错误(有的系统并不会返回错误).可以看到,UDP并不会为
用户程序维护一个状态.