
吊打面试官系列——万字长文计算机网络篇面试题(一)

TCP报文格式及首部含义?

-
头部长度:通常为20字节,有选项时更长
-
这里头部长度的1指代的是32位,即4个字节长度
-
因此4位的首部长度能够表示60字节
-
-
报文序号
-
标识报文中的第一个数据字节的序号
-
到达2^32-1后,重新回到0开始计数
-
初始连接请求报文中,SYN标志位也占1,因此第一字节序号为ISN+1
-
-
确认序号
-
接收方期望接收的下一个数据字节的序号
-
ACK为1时有效
-
-
校验和
- 由首部和数据一起运算得到,用来校验报文数据是否丢失
-
紧急指针
-
紧急数据字节号(urgSeq)=TCP报文序号(seq)+紧急指针(urgpoint)−1
-
正偏移量
-
-
选项
- 常见的是MSS(最大报文大小),指明本端能够接收的最大长度的报文段
-
窗口大小
-
16位的窗口大小最多能放65536字节
-
如果想要使用更大的窗口,可以在选项中添加窗口的缩放比例因子来进行扩大,比例为0-14
-
IP报文格式及首部含义?

-
头部长度:通常20字节,有选项时更长,总共不超过60字节
-
校验和
-
仅对IP首部计算校验和
-
TCP、UDP、ICMP等协议均在各自的首部中包含覆盖首部和数据的校验和
-
-
挂载协议标识
- 用来表示上层的传输层协议使用的是什么协议
-
分段偏移
- 当原始报文过大,以以太网帧为例,当大于1500字节的时候,会对原始报文进行分割,此时该字段就用来表示该分段在原始报文的位置
UDP报文格式及首部含义?

-
主要组成:源端口号、目标端口号、报文长度、检验和,一共8字节
-
报文长度
- 指首部和数据的总字节长度
UDP伪首部作用?
-
伪首部的出现:发送方或接收方根据IP报文首部获得8字节的源地址+目的地址、2字节的0字段+UDP协议字段、2字节的数据长度,得到12字节伪首部,临时添加在首部前面
-
伪首部的消失:发送方将计算完毕的校验和填入首部的校验和字段后,去除伪首部发送UDP报文
-
作用:仅仅是为了计算校验和
TCP三次握手的流程?

-
假设 A 为客户端,B 为服务器端。
-
在SYN建立连接的阶段会携带MSS选项字段来决定MSS报文的大小
-
默认是536字节,如果双方协商不成功
-
首先 B 处于 LISTEN(监听)状态,等待客户的连接请求。
-
A 向 B 发送连接请求报文,SYN=1,ACK=0,选择一个初始的序号 x。
-
B 收到连接请求报文,如果同意建立连接,则向 A 发送连接确认报文,SYN=1,ACK=1,确认号为 x+1,同时也选择一个初始的序号 y。
-
与此同时,B会将该连接放进半连接队列(SYN队列)
-
A 收到 B 的连接确认报文后,还要向 B 发出确认,确认号为 y+1,序号为 x+1。
-
此时A已经可以携带数据
-
B 收到 A 的确认后,连接建立。
-
此时,B的内核会将该连接从半连接队列中移除,然后创建新的完全连接,并添加到accept队列(全连接队列),等待应用程序调用accept函数取出来
-
为什么需要三次握手?
-
防止历史连接请求初始化了连接
-
第三次握手是为了防止失效的连接请求到达服务器,让服务器错误打开连接。
-
客户端发送的连接请求如果在网络中滞留,那么就会隔很长一段时间才能收到服务器端发回的连接确认。客户端等待一个超时重传时间之后,就会重新请求连接。但是这个滞留的连接请求最后还是会到达服务器,如果不进行三次握手,那么服务器就会打开两个连接。如果有第三次握手,客户端会根据上下文(如确认号)判断服务端发来的确认连接是否是历史连接(此时客户端不处于SYN-SENT状态),如果是,客户端则发送RST报文,终止历史连接,避免错误打开连接。
-
-
同步双方初始序列号
-
在TCP协议中,报文的序列号和确认号是确保消息可靠送达的重要机制
-
因此,需要正确同步双方的初始序列号。而同步一方的初始序列号,需要一次请求报文和响应报文。因此,确认双方的初始序列号,需要进行三次握手
-
当客户端发送携带「初始序列号」的
SYN报文的时候,需要服务端回一个ACK应答报文,表示客户端的 SYN 报文已被服务端成功接收,那当服务端发送「初始序列号」给客户端的时候,依然也要得到客户端的应答回应, 这样一来一回,才能确保双方的初始序列号能被可靠的同步
-
-
避免资源浪费
- 与第一点相似,主要是为了避免重开连接导致浪费系统资源
三次握手过程中未收到对方回复会怎么样?
-
服务端未收到第一次握手信息
-
服务端本身不会干什么,因为它还没有收到连接请求
-
客户端会不断地重试发送
-
-
客户端没有收到第二次握手信息
- 服务端的响应由于网络原因一直没有抵达客户端,此时服务端会不断重试
-
服务端没有收到第三次握手信息
-
服务端没有收到客户端的确认信息,这时候服务端会重传报文,如果重传次数达到上限时仍然没有收到确认报文,那么accept会返回-1,此时服务端这边的连接建立失败
-
此时客户端已经进入连接状态,可以发送消息了,但是服务端的连接失败了(accept返回-1),此时客户端再向服务端发送数据,服务端在收到后会发送RST报文给客户端
-
如何绕过三次握手?
-
在普通的三次握手的流程中,头两次握手的期间是不能携带数据的
-
也就是必须等到一个RTT时间后才能发送数据
-
使用TCP Fast Open,可以减少TCP建立连接发送数据的延迟
在客户端首次建立连接时的过程:
-
客户端发送 SYN 报文,该报文包含 Fast Open 选项,且该选项的 Cookie 为空,这表明客户端请求 Fast Open Cookie;
-
支持 TCP Fast Open 的服务器生成 Cookie,并将其置于 SYN-ACK 数据包中的 Fast Open 选项以发回客户端;
-
客户端收到 SYN-ACK 后,本地缓存 Fast Open 选项中的 Cookie。
所以,第一次发起 HTTP GET 请求的时候,还是需要正常的三次握手流程。
之后,如果客户端再次向服务器建立连接时的过程:
-
客户端发送 SYN 报文,该报文包含「数据」(对于非 TFO 的普通 TCP 握手过程,SYN 报文中不包含「数据」)以及此前记录的 Cookie;
-
支持 TCP Fast Open 的服务器会对收到 Cookie 进行校验:如果 Cookie 有效,服务器将在 SYN-ACK 报文中对 SYN 和「数据」进行确认,服务器随后将「数据」递送至相应的应用程序;如果 Cookie 无效,服务器将丢弃 SYN 报文中包含的「数据」,且其随后发出的 SYN-ACK 报文将只确认 SYN 的对应序列号;
-
如果服务器接受了 SYN 报文中的「数据」,服务器可在握手完成之前发送「数据」, 这就减少了握手带来的 1 个 RTT 的时间消耗 ;
-
客户端将发送 ACK 确认服务器发回的 SYN 以及「数据」,但如果客户端在初始的 SYN 报文中发送的「数据」没有被确认,则客户端将重新发送「数据」;
-
此后的 TCP 连接的数据传输过程和非 TFO 的正常情况一致。
所以,之后发起 HTTP GET 请求的时候,可以绕过三次握手,这就减少了握手带来的 1 个 RTT 的时间消耗。
初始序列号 ISN 是如何随机产生的?
起始 ISN 是基于时钟的,每 4 毫秒 + 1,转一圈要 4.55 个小时。
RFC1948 中提出了一个较好的初始化序列号 ISN 随机生成算法。
ISN = M + F (localhost, localport, remotehost, remoteport)
-
M是一个计时器,这个计时器每隔 4 毫秒加 1。 -
F是一个 Hash 算法,根据源 IP、目的 IP、源端口、目的端口生成一个随机数值。要保证 Hash 算法不能被外部轻易推算得出,用 MD5 算法是一个比较好的选择
既然 IP 层会分片,为什么 TCP 层还需要 MSS 呢?
- MTU 和 MSS

-
MTU:一个网络包的最大长度,以太网中一般为1500字节; -
MSS:除去 IP 和 TCP 头部之后,一个网络包所能容纳的 TCP 数据的最大长度; -
假设TCP的报文均由IP层进行分片;
-
当TCP的报文长度大于MTU时,报文会进行分片,然后发送给目标主机,再由目标主机进行组装,上传到传输层
-
然而,如果有一个IP分片丢失了,那么整个IP报文需要重传
-
因为IP层本身无超时重传机制,超时重传机制是靠传输层的TCP来保证的;
-
当接收方发现TCP报文中的一片丢失后,不会响应对应报文的ACK给对方,发送方在超时后就会重发TCP报文
-
到达IP层后则需再次分片发送,效率低下
-
针对上述情况,为了达到最佳的传输性能,TCP 协议在 建立连接的时候通常要协商双方的 MSS 值 ,当 TCP 层发现数据超过 MSS 时,则就先会进行分片,当然由它形成的 IP 包的长度也就不会大于 MTU ,自然也就不用 IP 分片了

- 经过 TCP 层分片后,如果一个 TCP 分片丢失后, 进行重发时也是以 MSS 为单位 ,而不用重传所有的分片,大大增加了重传的效率。
SYN攻击是什么?
-
TCP 连接建立是需要三次握手,假设攻击者短时间伪造不同 IP 地址的
SYN报文,服务端每接收到一个SYN报文,就进入SYN_RCVD状态,但服务端发送出去的ACK + SYN报文,无法得到未知 IP 主机的ACK应答,久而久之就会 占满服务端的 SYN 接收队列(未连接队列) ,使得服务器不能为正常用户服务 -
一旦服务端接收到SYN后,会为该连接分配一个TCB(Transmission Control Block),通常一个TCB至少需要280个字节,在某些操作系统中TCB甚至需要1300个字节
-
半连接队列的个数一般是有限的,在SYN攻击下,服务器会打开大量的半连接,分配TCB,从而耗尽服务器的资源,使得正常的连接请求无法得到响应
1. SYN攻击的分类有哪些?
-
Direct Attack 直接攻击
-
攻击方使用固定的源地址发起攻击
-
这种比较容易预防,只要将特定的IP列入黑名单即可
-
-
Spoofing Attack 攻击方使用变化的源地址发起攻击
-
Distributed Direct Attack 这种攻击主要是使用僵尸网络进行固定源地址的攻击
2 SYN攻击的解决方法有什么?
-
主要针对后两种攻击
-
修改Linux 内核参数,控制队列大小和当队列满时应做什么处理
-
当网卡接收数据包的速度大于内核处理的速度时,会有一个队列保存这些数据包。控制该队列的最大值如下参数:
net.core.netdev_max_backlog -
SYN_RCVD 状态连接的最大个数:
net.ipv4.tcp_max_syn_backlog -
超出处理能时,对新的 SYN 直接回 RST,丢弃连接:
net.ipv4.tcp_abort_on_overflow
-
-
开启 tcp_syncookies 功能
-
sysctl -w net.ipv4.tcp_syncookies=1
-
本质上属于延缓TCB分配方法
-
收到SYN攻击,会导致SYN队列被占满,对于后续来到的SYN请求,不再放在队列中,而是直接回应一个带SYN cookie的SYN-ACK包给客户端
-
服务器根据当前状态计算出一个值,放在己方发出的 SYN+ACK 报文中发出,当客户端返回 ACK 报文时,取出该值验证,如果合法,就认为连接建立成功,然后放到accept队列
-
后续应用程序调用accept()从accept队列中取出连接
-
-
增大半连接队列
-
增大半连接队列,我们得知不能只单纯增大 tcp_max_syn_backlog 的值,还需一同增大 somaxconn 和 backlog,也就是增大全连接队列
-
sysctl -w net.ipv4.tcp_max_syn_backlog=2048
-
-
减少 SYN+ACK 重传次数
-
减少 SYN+ACK 的重传次数,以加快处于 SYN_REVC 状态的 TCP 连接断开
-
sysctl -w net.ipv4.tcp_synack_retries=3
sysctl -w net.ipv4.tcp_syn_retries=3
-
-
全连接队列和半连接队列一起构成未决连接队列,这个队列的大小为backlog,是listen的参数
3 SYN cookie是什么?
-
服务器端根据本次连接的信息、时间生成一个SYN cookie做为报文初始序号
-
当客户端收到后,会向服务端发送响应报文
-
服务端根据响应报文的确认号-1就可以得到之前的SYN cookie
-
对SYN cookie按照规则进行解析就可以判断响应是否超时,以及连接信息是否有伪装等,避免浪费服务器的资源
TCP控制位有哪些?分别有什么用?
- SYN(synchronous建立联机)
* 用于建立连接,该报文的序列号用于初始序号的确定
- ACK(acknowledgement 确认)
* 表示当前报文的应答字段有效
* 除了最初的SYN报文外,其它报文必须将该位设置为1
- PSH(push传送)
* 接收方应该尽快将报文提交给应用层
* 为0则可以先进行缓存
- FIN(finish结束)
* 表示今后不会再有数据发送,希望断开连接
* 通信结束后,双方交换fin报文结束通信
- RST(reset重置)
* TCP连接出现异常,必须强制断开连接
* 常见情况:连接请求到达时,目标端口没有进程在监听
- URG(urgent紧急)
* 表示包中有需要紧急处理的数据,结合紧急指针一起使用
- Sequence number(顺序号码)
* 对字节流进行标号,表示第一个字节的编号
- Acknowledge number(确认号码)
* 期望收到的下一个报文的序号
TCP首部格式以及字段含义?

-
序号:
- 用于对字节流进行编号。例如序号为 301,表示第一个字节的编号为 301,如果携带的数据长度为 100字节,那么下一个报文段的序号应为 401。
-
确认号 :
- 期望收到的下一个报文段的序号。例如 B 正确收到 A 发送来的一个报文段,序号为 501,携带的数据长度为 200 字节,因此 B 期望下一个报文段的序号为 701,B 发送给 A 的确认报文段中确认号就为 701。
-
数据偏移 :
- 指的是数据部分距离报文段起始处的偏移量,实际上指的是首部的长度。
-
确认 ACK :
- 当 ACK=1 时确认号字段有效,否则无效。TCP 规定,在连接建立后所有传送的报文段都必须把ACK 置 1
-
同步 SYN :
- 在连接建立时用来同步序号。当 SYN=1,ACK=0 时表示这是一个连接请求报文段。若对方同意建立连接,则响应报文中 SYN=1,ACK=1。
-
终止 FIN :
- 用来释放一个连接,当 FIN=1 时,表示此报文段的发送方的数据已发送完毕,并要求释放连接。
-
窗口 :
- 窗口值作为接收方让发送方设置其发送窗口的依据。之所以要有这个限制,是因为接收方的数据缓存空间是有限的。
四次挥手的流程?

以下描述不讨论序号和确认号,因为序号和确认号的规则比较简单。并且不讨论 ACK,因为 ACK 在连接建立之后都为 1。
-
A 发送连接释放报文,FIN=1。
-
B 收到之后发出确认,此时 TCP 属于半关闭状态,B 能向 A 发送数据但是 A 不能向 B 发送数据。
-
当 B 不再需要连接时,发送连接释放报文,FIN=1。
-
A 收到后发出确认,进入 TIME-WAIT 状态,等待 2 MSL(最大报文存活时间)(Linux 系统里
2MSL默认是60秒)后释放连接。 -
B 收到 A 的确认后释放连接。
为什么需要4次挥手?
客户端发送了 FIN 连接释放报文之后,服务器收到了这个报文,就进入了 CLOSE-WAIT
状态。这个状态是为了让服务器端发送还未传送完毕的数据,传送完毕之后,服务器会发送 FIN 连接释放报文。 TIME_WAIT 客户端接收到服务器端的
FIN 报文后进入此状态,此时并不是直接进入 CLOSED 状态,还需要等待一个时间计时器设置的时间 2MSL。这么做有两个理由:
-
确保最后一个确认报文能够到达。如果 B 没收到 A 发送来的确认报文,那么就会重新发送连接释放请求报文,A 等待一段时间就是为了处理这种情况的发生。
-
至少允许报文丢失一次
-
等待一段时间是为了让本连接持续时间内所产生的所有报文都从网络中消失,使得下一个新的连接不会出现旧的连接请求报文。
四次挥手可以变为三次吗?
-
一种情况时延迟确认,将第二步的ack与第三步的fin包一起发送给对端
-
另外一种是服务端已经没有什么数据要发送了,就可以将fin和ack合并一个包发送给对端
FIN-WAIT2等待时间是多少?
- 主动关闭的一端调用完close以后(即发FIN给被动关闭的一端, 并且收到其对FIN的确认ACK)则进入FIN_WAIT_2状态。 如果这个时候因为网络突然断掉、被动关闭的一段宕机等原因,导致主动关闭的一端不能收到被动关闭的一端发来的FIN(防止对端不发送关闭连接的FIN包给本端) ,这个时候就需要FIN_WAIT_2定时器, 如果在该定时器超时的时候,还是没收到被动关闭一端发来的FIN,那么直接释放这个链接,进入CLOSE状态
针对 TCP 应该如何 Socket 编程?

-
流程:
-
服务端和客户端初始化
socket,得到文件描述符; -
服务端调用
bind,将监听socket绑定在 IP 地址和端口; -
服务端调用
listen,进行监听; -
服务端调用
accept,等待客户端连接; -
客户端调用
connect,向服务器端的地址和端口发起连接请求; -
服务端
accept返回用于传输的socket的文件描述符; -
客户端调用
write写入数据;服务端调用read读取数据; -
客户端断开连接时,会调用
close,那么服务端read读取数据的时候,就会读取到了EOF,待处理完数据后,服务端调用close,表示连接关闭。 -
注意点:
-
服务端调用
accept时,连接成功了会返回一个已完成连接的 socket,后续用来传输数据 -
所以,监听的 socket 和真正用来传送数据的 socket,是「两个」 socket,一个叫作 监听 socket ,一个叫作 已完成连接 socket
-
-
服务器:
-
fd:accept返回的连接描述字,每个连接有一个,生命周期为连接周期。
-
注:sockfd是监听描述字,一个服务器只有一个,用于监听是否有连接;fd是连接描述字,用于每个连接的操作。
-
fd:连接描述字。
-
buf:缓冲区buf。
-
count:缓冲区长度。
-
注:大于0表示读取的字节数,返回0表示文件读取结束,小于0表示发生错误。
-
sockfd:服务器socket描述字。
-
addr:指向地址结构指针。
-
addrlen:协议地址长度。
-
注:一旦accept某个客户机请求成功将返回一个全新的描述符用于标识具体客户的TCP连接。
-
sockfd:要监听的sock描述字。
-
backlog:socket可以排队的最大连接数。
-
sockfd:socket返回的套接字描述符,类似于文件描述符fd。
-
addr:有个sockaddr类型数据的指针,指向的是被绑定结构变量。
-
addrlen:地址长度。
-
domain:协议域,决定了socket的地址类型,IPv4为AF_INET。
-
type:指定socket类型,SOCK_STREAM为TCP连接。
-
protocol:指定协议。IPPROTO_TCP表示TCP协议,为0时自动选择type默认协议。
-
创建socket -> int socket(int domain, int type, int protocol);
-
绑定socket和端口号 -> int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
// IPv4的sockaddr地址结构 struct sockaddr_in { sa_family_t sin_family; // 协议类型,AF_INET in_port_t sin_port; // 端口号 struct in_addr sin_addr; // IP地址 }; struct in_addr { uint32_t s_addr; } -
监听端口号 -> int listen(int sockfd, int backlog);
-
接收用户请求 -> int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
-
从socket中读取字符 -> ssize_t read(int fd, void *buf, size_t count);
-
关闭socket -> int close(int fd);
-
-
客户机:
-
fd:同服务器端fd。
-
fd、buf、count:同read中意义。
-
大于0表示写了部分或全部数据,小于0表示出错。
-
sockfd客户端的sock描述字。
-
addr:服务器的地址。
-
addrlen:socket地址长度。
-
创建socket -> int socket(int domain, int type, int protocol);
-
连接指定计算机 -> int connect(int sockfd, struct sockaddr* addr, socklen_t addrlen);
-
向socket写入信息 -> ssize_t write(int fd, const void *buf, size_t count);
-
关闭oscket -> int close(int fd);
-
HTTP协议和HTTPS协议的默认端口号?
-
http:80
-
https:443
http协议的流程?
-
首先进行域名解析。
-
浏览器发起HTTP请求。
-
接下来到了传输层,选择传输协议。TCP或者UDP,TCP是可靠的传输控制协议,对HTTP请求进行封装,加入了端口号等信息。
-
然后到了网络层,通过IP协议将IP地址封装为IP数据报;然后此时会用到ARP协议,主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址,找到目的MAC地址;
-
接下来到了数据链路层,把网络层交下来的IP数据报添加首部和尾部,封装为MAC帧,现在根据目的mac开始建立TCP连接,三次握手,接收端在收到物理层上交的比特流后,根据首尾的标记,识别帧的开始和结束,将中间的数据部分上交给网络层,然后层层向上传递到应用层;
-
服务器响应请求并返回客户端要的资源,传回给客户端;
-
断开TCP连接,浏览器对页面进行渲染呈现给客户端。
cookies和session的含义与区别?
-
Cookie :
-
会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
-
个性化设置(如用户自定义设置、主题等)
-
浏览器行为跟踪(如跟踪分析用户行为等)
-
Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器之后向同一服务器再次发起请求时被携带上,用于告知服务端两个请求是否来自同一浏览器。由于之后每次请求都会需要携带 Cookie 数据,因此会带来额外的性能开销(尤其是在移动环境下)。
-
用途:
-
-
Session :
- Session 是存储在 web 服务器端的一块信息。session 对象存储特定用户会话所需的属性及配置信息。当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。
-
不同:
-
**存取方式的不同:**Cookie 只能存储 ASCII 码字符串,而 Session 则可以存储任何类型的数据,因此在考虑数据复杂性时首选Session;
-
**隐私策略的不同:**Cookie 存储在浏览器中,容易被恶意查看。如果非要将一些隐私数据存在 Cookie 中,可以将 Cookie 值进行加密,然后在服务器进行解密。而Session存储在服务器上,不存在敏感信息泄露的风险。
-
**服务器压力的不同:**对于大型网站,如果用户所有的信息都存储在 Session 中,那么开销是非常大的,因此不建议将所有的用户信息都存储到 Session 中。而Cookie保管在客户端,不占用服务器资源。假如并发阅读的用户十分多,Cookie是很好的选择。关于Google、Baidu、Sina来说,Cookie或许是唯一的选择。
-
**浏览器支持的不同:**无论客户端做怎样的设置, session 都能够正常工作。当客户端禁用 cookie 时将无法使用 cookie。假如客户端浏览器不支持Cookie,需要运用Session以及URL地址重写。需要注意的是一切的用到Session程序的URL都要进行URL地址重写,否则Session会话跟踪还会失效。关于WAP应用来说,Session+URL地址重写或许是它唯一的选择
-
**跨域支持上的不同:**Cookie支持跨域名访问,例如将domain属性设置为“.biaodianfu.com”,则以“.biaodianfu.com”为后缀的一切域名均能够访问该Cookie。跨域名Cookie如今被普遍用在网络中,例如Google、Baidu、Sina等。而Session则不会支持跨域名访问。Session仅在他所在的域名内有效。
-
Http协议如何保证安全性?
- 重要的数据,要加密 :
* 比如用户名密码,我们需要加密,这样即使被抓包监听,他们也不知道原始数据是什么。
- 非重要数据,要签名 :
* 签名的目的是为了防止篡改,比如http://www.xxx.com/getnews?id=1,获取id为1的新闻,如果不签名那么通过id=2,就可以获取2的内容等等。怎样签名呢?通常使用sign,比如原链接请求的时候加一个sign参数,sign=md5(id=1),服务器接受到请求,验证sign是否等于md5(id=1),如果等于说明正常请求。这会有个弊端,假如规则被发现,那么就会被伪造,所以适当复杂一些,还是能够提高安全性的。
阻塞式io和非阻塞式io有什么区别?
-
读:
-
在阻塞条件下 ,如果没有发现数据在网络缓冲中会一直等待,当发现有数据的时候会把数据读到用户指定的缓冲区。但是如果这个时候读到的数据量比较少,比参数中指定的长度要小,read并不会一直等待下去,而是立刻返回。read的原则是数据在不超过指定的长度的时候有多少读多少,没有数据就会一直等待。所以一般情况下我们读取数据都需要采用循环读的方式读取数据,一次read完毕不能保证读到我们需要长度的数据,read完一次需要判断读到的数据长度再决定是否还需要再次读取。
-
**在非阻塞的情况下,**read的行为是如果发现没有数据就直接返回,如果发现有数据那么也是采用有多少读多少的进行处理.对于读而言, 阻塞和非阻塞的区别在于没有数据到达的时候是否立刻返回。
-
-
写:
-
**在阻塞的情况,**是会一直等待直到write完全部的数据再返回。
-
非阻塞写的情况 ,是采用可以写多少就写多少的策略。与读不一样的地方在于,有多少读多少是由网络发送端是否有数据传输到本地内核缓存为准。但是对于 可以写多少是由本地的网络堵塞情况为标准的,在网络阻塞严重的时候,网络层没有足够的内存来进行写操作,这时候就会出现写不成功的情况,阻塞情况下会尽可能(有可能被中断)等待到数据全部发送完毕,对于非阻塞的情况就是一次写多少算多少,没有中断的情况下也还是会出现write到一部分的情况。
-
网络协议有哪7层?
-
应用层
-
用户接口、应用程序;
-
Application典型设备:网关;
-
典型协议、标准和应用:TELNET、FTP、HTTP
-
-
表示层
-
数据表示、压缩和加密presentation
-
典型设备:网关
-
典型协议、标准和应用:ASCLL、PICT、TIFF、JPEG|MPEG
-
表示层相当于一个东西的表示,表示的一些协议,比如图片、声音和视频MPEG。
-
-
会话层
-
会话的建立和结束;
-
典型设备:网关;
-
典型协议、标准和应用:RPC、SQL、NFS、X WINDOWS、ASP
-
-
传输层
-
主要功能:端到端控制Transport;
-
典型设备:网关;
-
典型协议、标准和应用:TCP、UDP、SPX
-
-
网络层
-
主要功能:路由、寻址Network;
-
典型设备:路由器;
-
典型协议、标准和应用:IP、IPX、APPLETALK、ICMP;
-
-
数据链路层
-
主要功能:保证无差错的疏忽链路的data link;
-
典型设备:交换机、网桥、网卡;
-
典型协议、标准和应用:802.2、802.3ATM、HDLC、FRAME RELAY;
-
-
物理层
-
主要功能:传输比特流Physical;
-
典型设备:集线器、中继器
-
典型协议、标准和应用:V.35、EIA/TIA-232.
-
TCP和UDP的区别?
-
TCP:
-
可靠,稳定 TCP的可靠体现在TCP在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接用来节约系统资源。
-
慢,效率低,占用系统资源高,易被攻击。TCP在传递数据之前,要先建连接,这会消耗时间,而且在数据传递时,确认机制、重传机制、拥塞控制机制等都会消耗大量的时间,而且要在每台设备上维护所有的传输连接,事实上,每个连接都会占用系统的CPU、内存等硬件资源。而且,因为TCP有确认机制、三次握手机制,这些也导致TCP容易被人利用,实现DOS、DDOS、CC等攻击。
-
-
UDP:
-
快,比TCP稍安全 UDP没有TCP的握手、确认、窗口、重传、拥塞控制等机制,UDP是一个无状态的传输协议,所以它在传递数据时非常快。没有TCP的这些机制,UDP较TCP被攻击者利用的漏洞就要少一些。但UDP也是无法避免攻击的,比如:UDP Flood攻击……
-
不可靠,不稳定 因为UDP没有TCP那些可靠的机制,在数据传递时,如果网络质量不好,就会很容易丢包。
-
-
使用场景:
-
整个数据要准确无误的传递给对方,这往往用于一些要求可靠的应用,比如HTTP、HTTPS、FTP等传输文件的协议,POP、SMTP等邮件传输的协议。在日常生活中,常见使用TCP协议的应用如下:浏览器,用的HTTP FlashFXP,用的FTP Outlook,用的POP、SMTP Putty,用的Telnet、SSH QQ文件传输 …………
-
当对网络通讯质量要求不高的时候,要求网络通讯速度能尽量的快,这时就可以使用UDP。比如,日常生活中,常见使用UDP协议的应用如下:QQ语音 QQ视频 TFTP ……
-
-
区别小结:
-
TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
-
TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
-
TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的
-
UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)
-
每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
-
TCP首部开销20字节;UDP的首部开销小,只有8个字节(UDP的速度快,开销少)
-
TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道
-
-
参考文章:TCP和UDP的最完整的区别
HTTP的常用方法
-
GET:
-
获取资源
-
当前网络请求中,绝大部分使用的是 GET 方法。
-
-
HEAD :
-
获取报文首部
-
和 GET 方法类似,但是不返回报文实体主体部分。
-
主要用于确认 URL 的有效性以及资源更新的日期时间等。
-
-
POST :
-
传输实体主体
-
POST 主要用来传输数据,而 GET 主要用来获取资源。
-
-
PUT :
-
上传文件
-
由于自身不带验证机制,任何人都可以上传文件,因此存在安全性问题,一般不使用该方法。
-
-
PATCH :
-
对资源进行部分修改
-
PUT 也可以用于修改资源,但是只能完全替代原始资源,PATCH 允许部分修改。
-
-
DELETE :
-
删除文件
-
与 PUT 功能相反,并且同样不带验证机制。
-
-
OPTIONS :
-
查询支持的方法
-
查询指定的 URL 能够支持的方法。
-
会返回 Allow: GET, POST, HEAD, OPTIONS 这样的内容。
-
-
CONNECT :
-
要求在与代理服务器通信时建立隧道
-
使用 SSL(Secure Sockets Layer,安全套接层)和 TLS(Transport Layer Security,传输层安全)协议把通信内容加密后经网络隧道传输。
-
-
TRACE :
-
追踪路径
-
服务器会将通信路径返回给客户端。
-
发送请求时,在 Max-Forwards 首部字段中填入数值,每经过一个服务器就会减 1,当数值为 0 时就停止传输。
-
通常不会使用 TRACE,并且它容易受到 XST 攻击(Cross-Site Tracing,跨站追踪)。
-
Http get和post的区别?
-
根据http规范,get用于信息获取,应该是安全的和幂等的
-
安全意味着该操作用于获取信息而非修改信息。换句话说,GET 请求一般不应产生副作用。
-
幂等的意味着对同一URL的多个请求应该返回同样的结果。
-
-
根据http规范,POST表示可能修改变服务器上的资源的请求,即post用于提交数据。
-
get提交参数追加在url后面,post参数可以通过http body提交。
-
get的url会有长度上的限制,则post的数据则可以非常大,post的数据量受限于处理程序的处理能力。
-
get提交信息明文显示在url上,不够安全,post提交的信息不会在url上显示
-
get提交可以被浏览器缓存,post不会被浏览器缓存。
-
登录页面有可能被浏览器缓存
-
其他人可以看到浏览器的历史记录
-
-
get参数只能使用ascii码,post参数可以使用标准字符集
URL和URI的区别?
-
URI包括URL和URN两个类别,URL是URI的子集,所以URL一定是URI,而URI不一定是URL
-
URI:
-
Universal Resource Identifier 统一资源标志符
-
用来标识抽象或物理资源的一个紧凑字符串。
-
-
URL :
-
Universal Resource Locator 统一资源定位符.
-
一种定位资源的主要访问机制的字符串,一个标准的URL必须包括:protocol、host、port、path、parameter、anchor。
-
-
URN :
-
Universal Resource Name 统一资源名称.
-
通过特定命名空间中的唯一名称或ID来标识资源。
-
从浏览器中输入url之后发生了什么?
-
深入浅出经典面试题:从浏览器中输入URL到页面加载发生了什么
-
DNS查询
-
先在本地域名服务器中根据域名查询IP
-
向根域名服务器发送请求,查找IP
-
向顶级域名服务器发送请求,查找IP
-
-
TCP连接
-
发送HTTP请求
-
Server处理HTTP请求并返回HTTP报文
-
浏览器解析并渲染页面
-
连接断开
-
域名解析 --> 发起TCP的3次握手 --> 建立TCP连接后发起http请求 --> 服务器响应http请求,浏览器得到html代码 --> 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等) --> 浏览器对页面进行渲染呈现给用户。
域名解析每次都去访问根域名服务器的话,根域名服务器压力不会很大吗?DNS优化方法?
-
浏览器缓存
-
系统缓存
-
路由器缓存
-
IPS服务器缓存
-
根域名服务器缓存
-
顶级域名服务器缓存
-
主域名服务器缓存
OSI七层协议模型、TCP/IP四层模型和五层协议体系结构之间的关系?
- OSI七层协议模型、TCP/IP四层模型和五层协议体系结构之间的关系

osi为什么有了七层还有五层的概念?
-
七层协议的理论虽然完整,但是不太实用而且很复杂
-
四层结构是实现模型,而5层结构则是结合两种模型得出的,目的是为了更好描述网络接口层