计算机网络 TCP/IP协议

1、tcp和udp的区别

TCP(Transfer Control Protocol:传输控制协议,面向连接的流传输控制协议,具有高可靠性,确保传输数据的正确性,有验证重发机制,因此不会出现丢失或者乱序。(保证在不可靠的信道上实现可靠的传输,适用于文件下载,支付等)

UDP(User Datagram Protocol):用户数据报协议,无连接的数据服务,不对数据报进行检查和修改,无需等到对方的应答,会出现分组丢失、重复、乱序,但是具有较好的实时性,UDP段结构比TCP的段结构简单,因此网络开销也小。(适用于语音通话,视频直播等)

面向报文和面向字节流:

  • 面向报文的传输方式是:应用层交给UDP多长的报文,UDP就发送多长的报文,即一次发送一个报文,因此应用程序需要选择合适大小的报文
  • 面向字节流是:虽然应用程序和TCP的交互是一次一个数据块,但是TCP将数据块看做是一连串无结构的字节流。TCP中有一个缓冲,当程序传送的数据块太大,TCP就可以将数据块划分短一点在传送。

2、TCP的三次握手与四次挥手

  1. 三次握手:
    1. 客户端发送连接请求报文段,将syn(标记位)设置为1,seq为x;(Squence Number数据包序号),然后等待服务端确认,客户端进入SYN_SENT状态(请求连接);
    2. 服务端收到客户端的syn报文,对syn报文段进行确认,设置确认号ack为x+1(就是seq+1);同时自己还要发送syn请求信息,将syn设置为1,seq为y;服务端将上述所有的信息都放到SYN+ACK报文段中,一并发给客户端,此时服务器进入SYN_RECV状态;(SYN_RECV是指,服务端被动打开后,接收到了客户端的SYN并且发送了ACK时的状态。再进一步接收到客户端的ACK就进入ESTABLISHED状态。
    3. 客户端收到服务端的SYN+ACK报文段,然后将sck设置为y+1,向服务端发送ack报文,这个报文段发送成功后,客户端和服务端都进入ESTABLISHED状态;完成三次握手
  2. 四次挥手
    1. 客户端设置seq和ack,想服务器发送一个FIN(终结报文段),此时客户端进入FIN_WIAT_1状态,标识客户端没有东西要发给服务端了
    2. 服务端收到了客户端的FIN报文段,想客户端回一个ACK报文段
    3. 服务端想客户端发送FIN报文段,请求关闭连接,同事进入LAST_ACK状态
    4. 客户端收到服务端的FIN报文段后,向服务端发送ACK报文段,然后客户端进入TIME_WAIT状态,服务端收到客户端的 ACK 报文段以后,就关闭连接。此时,客户端等待 2MSL(指一个片段在网络中最大的存活时间)后依然没有收到回复,则说明服务端已经正常关闭,这样客户端就可以关闭连接了。
  3. 如果有大量的连接,每次连接都需要经历三次握手和四次挥手,显然会造成性能低下,因此http有一种长连接(keepalive connections)的机制,他可以在传输数据结束后仍然保持连接,当客户端需要再次获取数据的时候,直接使用刚刚空闲下的连接,而无需要再次握手。

3、为什么要进行三次握手?

确保自己可以确认“对方能够接收到自己的信息,并且可以做出正确的应答

为了保证服务端能收接受到客户端的信息并能做出正确的应答而进行前两次(第一次和第二次)握手,为了保证客户端能够接收到服务端的信息并能做出正确的应答而进行后两次(第二次和第三次)握手。

以打电话来举例:

1、A给B打电话:喂,能听到吗?

2、B回复:可以听到,你能听到我吗?

3、A回复:我也可以听到

4、AB双方都确认对方能够听到自己,可以进行后面的对话了。

4、单工、半双工和全双工的区别?

  • 单工:数据只能在一个方向上进行传输,不能实现双方的通信,如电视,广播
  • 半双工:运行数据在两个方向上传输,但是同一个时间数据只能在一个方向上传输,可以理解为切换方向的单工
  • 全双工:允许数据在两个方向同时传输

5、为什么要进行四次挥手?

TCP是属于全双工模式,当客户端发送FIN报文段的时候,表示客户端没有数据要发送了,因此客户端告诉服务端他的数据已经发完毕了,但是这个时候客户端还可以接受服务器发送来的数据;当服务端也发送了FIN报文段,才表示服务端也没有数据要发送了,客户端接受到信息并告知服务端后,才会愉快的终端这次TCP连接。

还是打电话举例:

1、A给B说:我的话说完了

2、B回复:好的,我知道了

3.1、B告诉A:我还有几点要说(然后巴拉巴拉。。。表明这次电话还有信息没说完,不能挂断)

3.2、B告诉A:我也说完了

4、A:我知道了;然后就可以挂断电话了

6、为什么要等待 2MSL?

(1)为了保证A发送的最后一个ACK报文段能够到达B。这个ACK报文段有可能丢失,因而使处在LAST_ACK状态的B收不到对已发送的FIN+ACK报文段的确认。
B会超时重传这个FIN+ACK报文段,而A就能在2MSL时间内收到这个重传的FIN+ACK报文段。
接着A重传一次确认,重新启动2MSL计时器。
最后,A和B都正常进入到CLOSED状态。如果A在TIME-WAIT状态不等待一段时间,而是在发送完ACK报文段后立即释放连接,那么就无法收到B重传的FIN+ACK报文段,因而也不会再发送一次确认报文段。
这样,B就无法按照正常步骤进入CLOSED状态。

(2)“已失效的连接请求报文段”出现在本连接中。A在发送完最后一个ACK报文段后,再经过时间2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。
这样就可以使下一个新的连接中不会出现这种旧的连接请求报文段。
B只要收到了A发出的确认,就进入CLOSED状态。
同样,B在撤销相应的传输控制块TCB后,就结束了这次的TCP连接。我们注意到,B结束TCP连接的时间要比A早一些。
 

7、IP 网络互连协议:定义一台网络上的计算机,是唯一的

IP地址的分类:

  1. ipv4 / ipv6
    1. ipv4:四个字节组成,每个字节0~255 如本机localhost:127.0.0.1
    2. ipv6:总长度为128比特,通常分为8组,每组为4个十六进制数的形式,每组十六进制数间用冒号分隔,如 FC00:0000:130F:0000:0000:09C0:876A:130B
  2. 公网(互连网) /  私网(局域网)
    1. ABCD类地址
    2. 192.168.xx.xx,专门给组织内部使用的

域名:记忆IP

java中的 InetAddress对象
    
    public static void main(String[] args) throws IOException {
        // 通过域名获取百度的 InetAddress对象
        InetAddress baidu = InetAddress.getByName("www.baidu.com");
        // 获取主机名
        System.out.println(baidu.getHostName());
        // 获取主机地址
        System.out.println(baidu.getHostAddress());
        // 看看5s内能否连通百度
        System.out.println(baidu.isReachable(5000));
    }


System.out.println(InetAddress.getByName("www.baidu.com")); // www.baidu.com/14.215.177.38
System.out.println(InetAddress.getByName("localhost"));//localhost/127.0.0.1

8、端口

  1. 端口表示计算机上一个程序的进程;端口号属于传输协议的一部分,可以说,数据通过 IP 地址发送对应的数据到指定设备上,而通过端口号把数据发送到指定的服务或程序上
  2. 程序一般不止是监听指定的端口号,而且也会明确对应的传输协议。所以我们在进行数据传输的时候,既要指定对应的端口号,也要指定对应的通讯协议,很多人仅仅会说:程序 A 监听着 33001 端口,这个是不正确的,至少是不完全正确的。相应的,我们应该这样说:程序 A 使用 TCP 协议,监听 33001 端口,当然你也可以说:程序 A 使用 UDP 协议,监听 33001 端口。
  3. 指定传输协议和端口,显而易见的好处在于,当我们进行端口转发或者构建网络防火墙的时候,我们可以很方便的通过协议和端口进行隔离。以防止不可预见的意外发生。对于计算机来说,通过这种方式可以防止外网各种不必要的数据,进入本地局域网。
     
  • 不同的进程有不同的端口,用来区分软件
  • 端口号为0~65535,单个协议下端口号不能冲突
  • TCP/UDP 可以使用同样的端口,因为他们协议不一样
  • 端口分类:
    • 公有端口 0~1023
      • HTTP 80
      • HTTPS 443
      • FTP 21
    • 程序注册端口:1024~49151
      • Tomcat 8080
      • MySQL 3306
      • oracle 1521
    • 动态、私有 49152~65535
      • netstat -ano #查看所有端口
      • netstat -ano|findstr “8080” # 查看指定端口
      • tasklist|findstr "8080" #查看指定端口的进程

9、模拟TCP实现聊天

代码如下,先启动服务端,然后启动客户端,可以在控制台查看;

启动服务端的时候,控制台一直处于监听状态,启动客户端后,连接成功,服务端的控制台打印客户端传来的信息,然后两个都关闭。

对于TCP连接:

1.服务器端

1)创建套接字create;

2)绑定端口号bind;

3)监听连接listen;

4)接受连接请求accept,并返回新的套接字;

5)用新返回的套接字recv/send;

6)关闭套接字。

2.客户端

1)创建套接字create;

2)发起建立连接请求connect;

3)发送/接收数据send/recv;

4)关闭套接字。

TCP总结:

Server端:create – bind – listen–  accept–  recv/send– close

Client端:create——- conncet——send/recv——close.

// 服务端
public class TestTCPSever {
    public static void main(String[] args) throws IOException {
        // 服务端有一个地址
        ServerSocket serverSocket = new ServerSocket(9999);
        // 等待客户端连接过来
        Socket socket = serverSocket.accept();
        // 读取客户端的消息
        InputStream is = socket.getInputStream();
        // 管道流
        ByteArrayOutputStream bs = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = is.read(buffer)) != -1) {
            bs.write(buffer, 0, len);
        }
        System.out.println(bs);

        bs.close();
        is.close();
        socket.close();
        serverSocket.close();
    }
}

// 客户端
public class TestTCPClient {
    public static void main(String[] args) throws IOException {
        // 获得服务器的地址和端口号
        InetAddress serverIp = InetAddress.getByName("127.0.0.1");
        int port = 9999;
        // 创建一个socket连接
        Socket socket = new Socket(serverIp, port);
        // 发消息 IO流
        OutputStream os = socket.getOutputStream();
        os.write("你好!".getBytes(StandardCharsets.UTF_8));
        os.close();
        socket.close();
    }
}

10、什么是同步,什么是异步?

同步:如果有多个任务或者事件要发生,这些任务或者事件必须逐个进行,一个事件任务的执行会导致整个流程的暂时等待,其他事件没有办法并发的执行下去;

异步:如果有多个任务或者事件要发生,那么这些事件可以并发的执行

例子:一个任务包括两个子任务A和B,同步时,A执行过程中B只能等待,直到A执行完毕后,B才能继续执行;异步时,AB可以并发的执行,B不用等待A执行结束。

11、什么是阻塞,什么是非阻塞?

阻塞:某个事件或者任务执行过程中,发出一个请求,但是由于该请求操作需要的条件不满足而无法继续执行时,他就一直在那等待,直到条件满足后继续执行;

非阻塞:某个事件或者任务执行过程中,发出一个请求,如果该请求操作需要的条件不满足,会立即返回一个标志信息告知条件不满足,不会一直等待。

举个简单的例子:

假如我要读取一个文件中的内容,如果此时文件中没有内容可读,对于同步来说就是会一直在那等待,直至文件中有内容可读;而对于非阻塞来说,就会直接返回一个标志信息告知文件中暂时无内容可读。

阻塞和非阻塞着重点在于发出一个请求操作时,如果进行操作的条件不满足是否会返会一个标志信息告知条件不满足。理解阻塞和非阻塞可以同线程阻塞类比地理解,当一个线程进行一个请求操作时,如果条件不满足,则会被阻塞,即在那等待条件满足。

12、什么是TCP粘包,产生原因和解决办法

TCP粘包是指发送方发送的若干包数据到接收方时,粘成一包,从缓冲区看,后一包的数据头紧结着前一包的数据尾。粘包可能由发送方造成,也可能由接收方造成。只有TCP会产生粘包现象(UDP有消息保护边界)。

粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据造成的。(TCP是一个面向流的协议,像流一样源源不断传输应用层的数据,并不管应用层的数据包之间的分界。)

  • 发送端原因:由于TCP协议本身的机制(可靠的,面向连接的,三次握手)客户端和服务端会维持一个连接(channel),数据在连接不断开的情况下,可以持续不断的将多个数据包发往服务器,如果发送的网络数据包太小,那么本身会启动Nagle算法对较小的包进行合并然后在发送(因此,TCP的网络延迟要比UDP的高,超时或者包大小足够的时候发送),这样的话,服务器在接收数据流的时候无法区分两个包之间的边界,就产生了粘包;
  • 接收端原因:服务端收到数据后,放到缓冲区,如果消息没有及时从缓冲区取走,下次读取数据的时候就会出现一次取到多个包的情况,造成粘包;

什么时候不需要处理粘包?

  1. 短连接的情况下无需考虑粘包;
  2. 发送方发送的多个分组本就是一个数据的不同部分,如一个很大的文件分成多个分组发送
  3. 如果多个分组毫不相干,或者是并列的关系,就必须要处理粘包问题了。

如何处理粘包现象?

1、发送方

对于发送方造成的粘包现象,可以通过关闭Nagle算法来解决,将TCP_NODELAY = true

TCP连接中启用和禁用TCP_NODELAY有什么影响?_韦伊的博客-CSDN博客_tcp_nodelay

2、接收方

TCP并没有处理接收方粘包现象的机制。只能在应用层进行解决

  1. 发送端给每个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了。
  2. 发送端将每个数据包封装为固定长度(不够的可以通过补0填充),这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。
  3. 可以在数据包之间设置边界,如添加特殊符号,这样,接收端通过这个边界就可以将不同的数据包拆分开。

13、GET和POST的区别?

POST和GET都是向服务器提交数据,并且都会从服务器获取数据。

1、传送方式:get通过地址栏传输,post通过报文传输。

2、传送长度:get参数有长度限制(受限于url长度),而post无限制

3、GET和POST还有一个重大区别,简单的说:GET产生一个TCP数据包;POST产生两个TCP数据包

对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);

而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

建议:

1、get方式的安全性较Post方式要差些,包含机密信息的话,建议用Post数据提交方式;

2、在做数据查询时,建议用Get方式;而在做数据添加、修改或删除时,建议用Post方式;
 

14、什么是拆包和粘包?

首先,UDP是没有拆包和粘包的,因为UDP是面向报文的,有消息保护边界

TCP因为是面向流的,数据没有边界,操作系统在发送TCP数据的时候,会通过缓冲区(一般是1024个字节)进行优化:

  • 如果一次发送的数据量比较大,超过了缓冲区大小,TCP就会将其拆分为多次发送,这就是拆包
  • 如果一次发送的数据量比较小,TCP则会将多个请求合并在一起,这就是粘包

其实这个包只是为了一种形象的说明,TCP因为是面向字节流的协议,因此不会有“包”这一概念。

常见的解决方案:

  • 发送端每次都发送固定的长度,不足长度用0补齐
  • 发送端在每个“包”的末尾使用固定的分隔符,如果发生了拆包,那就按照分隔符在进行合并,如FTP协议
  • 将消息分成消息头和消息尾,头部保存整个消息长度,只有读到足够长度才认为是一个完整的消息
  • 自定义协议进行粘包和拆包的处理。

散碎笔记:

TCP(Transfer Control Protocol):面向连接的,可靠的

socket :套接字 (源IP + port ,目标IP + port ,绝对唯一的连接)

port:最多65535个;

三次握手成功后,如果网断了,客户端或者服务端是无法感知断开的,但是内核会做连接的keepalive(心跳)检测连接是否健康。

拆包、粘包

全网最详细的网络协议之TCP/IP 协议,建议直接收藏_Java架构设计的博客-CSDN博客_网络tcpip

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值