1、 如何理解是 TCP 面向字节流协议?
udp是面向报文的 出去的 UDP 报文中的数据部分就是完整的用户消息,也就是每个 UDP 报文就是一个用户消息的边界,这样接收方在接收到 UDP 报文后,读一个 UDP 报文就能读取到完整的用户消息
当用户消息通过 TCP 协议传输时,消息可能会被操作系统分组成多个的 TCP 报文,也就是一个完整的用户消息被拆分成多个 TCP 报文进行传输。不能认为一个用户消息对应一个 TCP 报文,正因为这样,所以 TCP 是面向字节流的协议。
2、TCP 和 UDP 可以同时绑定相同的端口吗?
可以的。
TCP 和 UDP 传输协议,在内核中是由两个完全独立的软件模块实现的。当主机收到数据包后,可以在 IP 包头的「协议号」字段知道该数据包是 TCP/UDP,所以可以根据这个信息确定送给哪个模块(TCP/UDP)处理,送给 TCP/UDP 模块的报文根据「端口号」确定送给哪个应用程序处理。因此, TCP/UDP 各自的端口号也相互独立,互不影响
3、多个tcp服务进程可以绑定同一个端口吗?
如果两个 TCP 服务进程同时绑定的 IP 地址和端口都相同,那么执行 bind() 时候就会出错,错误是“Address already in use”。如果两个 TCP 服务进程绑定的端口都相同,而 IP 地址不同,那么执行 bind() 不会出错。
4、如何解决服务端重启时,报错“Address already in use”的问题?
当我们重启 TCP 服务进程的时候,意味着通过服务器端发起了关闭连接操作,于是就会经过四次挥手,而对于主动关闭方,会在 TIME_WAIT 这个状态里停留一段时间,这个时间大约为 2MSL。当 TCP 服务进程重启时,服务端会出现 TIME_WAIT 状态的连接,TIME_WAIT 状态的连接使用的 IP+PORT 仍然被认为是一个有效的 IP+PORT 组合,相同机器上不能够在该 IP+PORT 组合上进行绑定,那么执行 bind() 函数的时候,就会返回了 Address already in use 的错误。要解决这个问题,我们可以对 socket 设置 SO_REUSEADDR 属性。这样即使存在一个和绑定 IP+PORT 一样的 TIME_WAIT 状态的连接,依然可以正常绑定成功,因此可以正常重启成功
5、客户端的端口可以重复使用吗?
在客户端执行 connect 函数的时候,只要客户端连接的服务器不是同一个,内核允许端口重复使用。TCP 连接是由四元组(源IP地址,源端口,目的IP地址,目的端口)唯一确认的,那么只要四元组中其中一个元素发生了变化,那么就表示不同的 TCP 连接的
6、客户端 TCP 连接 TIME_WAIT 状态过多,会导致端口资源耗尽而无法建立新的连接吗?
要看客户端是否都是与同一个服务器(目标地址和目标端口一样)建立连接。如果客户端都是与同一个服务器(目标地址和目标端口一样)建立连接,那么如果客户端 TIME_WAIT 状态的连接过多,当端口资源被耗尽,就无法与这个服务器再建立连接了。即使在这种状态下,还是可以与其他服务器建立连接的,只要客户端连接的服务器不是同一个,那么端口是重复使用的。
7、如何解决客户端 TCP 连接 TIME_WAIT 过多,导致无法与同一个服务器建立连接的问题?
打开 net.ipv4.tcp_tw_reuse 这个内核参数。
因为开启了这个内核参数后,客户端调用 connect 函数时,如果选择到的端口,已经被相同四元组的连接占用的时候,就会判断该连接是否处于 TIME_WAIT 状态。如果该连接处于 TIME_WAIT 状态并且 TIME_WAIT 状态持续的时间超过了 1 秒,那么就会重用这个连接,然后就可以正常使用该端口了
8、tcp协议有什么缺陷
- 升级 TCP 的工作很困难;(内核中实现)
- TCP 建立连接的延迟;
- TCP 存在队头阻塞问题;(中间的包丢了,需要等待重传,阻塞该tcp连接中的所有请求)
- 网络迁移需要重新建立 TCP 连接(流量——wifi的切换)
9、拔掉网线后,原本的tcp连接还存在吗?掉网线这个动作并不会影响 TCP 连接的状态。
拔掉网线有数据传输,如果在服务端重传报文的过程中,客户端刚好把网线插回去了,无影响
但是没有的话就有影响了
拔掉网线没有数据传输,如果双方都没有开启tcp keepalive机制,则无感知,如果都开启了,也要看是否在探测时间内插回网线