TCP和UDP详细介绍

阅读:244

目录介绍

  • 1.TCP和UDP的区别
    • 1.1 UDP协议
    • 1.2 TCP协议
  • 2.Socket介绍
    • 2.1 Socket简单介绍
    • 2.2 Socket工作图解
  • 3.UDP协议传输数据
    • 3.1 客户端发送数据
    • 3.2 服务端接收数据
  • 4.TCP协议传输数据
    • 4.1 客户端发送数据
    • 4.2 服务端接收数据
  • 5.三次握手建立连接
    • 5.1 三次握手原理图
    • 5.2 为什么建立连接需要三次握手
    • 5.3 四次握手断开连接
  • 6.Socket文件传输

1.TCP和UDP的区别

1.1 TCP和UDP的区别

  • ①UDP协议:
    • 面向无连接
    • 每个数据报的大小在限制在64k内
    • 因为是面向无连接,所以是不可靠协议
    • 不需要建立连接,速度快
  • ②TCP协议:
    • 必须建立连接,形成传输数据的通道
    • 在连接中可进行大数据量传输
    • 通过三次握手完成连接,是可靠协议
    • 必须建立连接,效率会稍低
  • 注:三次握手:
    • 第一次:我问你:在么?
    • 第二次:你回答:在。
    • 第三次:我反馈:哦,我知道你在。

2.Socket介绍

2.1 Socket简单介绍

  • Socket简单介绍
    • Socket就是为网络服务提供的一种机制
    • 通信的两端都有Socket
    • 网络通信其实就是Socket间的通信
    • 数据在两个Socket间通过IO传输
    • 玩Socket主要就是记住流程,代码查文档就行
    • Socket的简单使用的话应该都会,两个端各建立一个Socket,服务端的叫ServerSocket,然后建立连接即可。

2.2 Socket工作图解

1.png

3.UDP协议传输数据

3.1 客户端发送数据

/**
 * 端口号
 */
private static final int PORT = 8080;

/*
 * UDP协议发送数据:
 * 1.创建发送端Socket对象
 * 2.创建数据,并把数据打包
 * 3.调用Socket对象发送方法发送数据包
 * 4.释放资源
 */
private void udpSendMessage(String serverAddress) {
    String content = "yang";
    // 创建发送端Socket对象
    try {
        // 创建发送端Socket对象
        DatagramSocket ds = new DatagramSocket();
        // 创建数据,并把数据打包
        byte[] bys = content.getBytes();
        InetAddress byName = InetAddress.getByName(serverAddress);
        DatagramPacket dp = new DatagramPacket(bys, bys.length,byName ,PORT);
        // 调用Socket对象发送方法发送数据包
        ds.send(dp);
        // 释放资源
        ds.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

3.2 服务端接收数据

/*
     * UDP协议接收数据:
     * 1.创建接收端Socket对象
     * 2.创建一个数据包(接收容器)
     * 3.调用Socket对象接收方法接收数据包
     * 4.解析数据包
     * 5.释放资源
     */
private void receive_udp() {
    try {
        // 创建接收端Socket对象
        DatagramSocket ds = new DatagramSocket(PORT);
        // 创建一个数据包(接收容器)
        byte[] bys = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bys, bys.length);
        // 调用Socket对象接收方法接收数据包
        ds.receive(dp);
        // 获取对方的ip
        String ip = dp.getAddress().getHostAddress();
        // 解析数据
        String data = new String(dp.getData(), 0, dp.getLength());
        Message message = new Message();
        message.obj = data;
        message.what = 2;
        handler.sendMessage(message);
        // 关闭数据库
        ds.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

4.TCP协议传输数据

4.1 客户端发送数据

/**
 * 端口号
 */
private static final int PORT = 8080;

/**
 * @param serverAddress 要发送到服务端的ip
 * 1.创建socket并指定ip和端口号
 * 2.获取输出流,写数据
 * 3.释放资源
 * 4.Tcp一定要先开接收端
 */
public void send_tcp(String serverAddress) {
    try {
        Socket s = new Socket(serverAddress, PORT);
        //为了发送数据,应该获得socket流中的输出流
        OutputStream out = s.getOutputStream();
        String content = "yang";
        out.write(content.getBytes());
        s.close();
    } catch (UnknownHostException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

4.2 服务端接收数据

/**
 * TCP协议接收数据
 * 1.创建接收端的Socket对象
 * 2.监听客户端接收,返回一个Socket对象
 * 3.获取输入流,读取数据显示在控制台
 * 4.释放资源
 */
public void receive_tcp() {
    try {
        //1.建立连接,监听端口
        ServerSocket ss = new ServerSocket(PORT);
        //2.连接客户端对象
        while (true) {
            //阻塞式方法,只有客户端连接了才会继续往下运行
            Socket accept = ss.accept();
            //获取ip
            String ip = accept.getInetAddress().getHostAddress();
            //3.获取客户端发送过来的数据
            InputStream in = accept.getInputStream();
            //4.开始读取,获取输入信息
            BufferedReader bff = new BufferedReader(new InputStreamReader(in));
            //读取信息
            String line;
            final StringBuilder sb = new StringBuilder();
            while ((line = bff.readLine()) != null) {
                sb.append(line);
            }
            Message message = new Message();
            message.obj = sb.toString();
            handler.sendMessage(message);
            //5.关闭
            //ss.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

5.三次握手建立连接

5.1 三次握手原理图

  • 第一次:发送SNY=1表示此次握手是请求建立连接的,然后seq生成一个客户端的随机数X
  • 第二次:发送SNY=1,ACK=1表示是回复请求建立连接的,然后ack=客户端的seq+1(这样客户端收到后就能确认是之前想要连接的那个服务端),然后把服务端也生成一个代表自己的随机数seq=Y发给客户
  • 端。
  • 第三次:ACK=1。 seq=客户端随机数+1,ack=服务端随机数+1(这样服务端就知道是刚刚那个客户端了) 

1.jpeg

5.2 为什么建立连接需要三次握手

  • 首先非常明确的是两次握手是最基本的,第一次握手,C端发了个连接请求消息到S端,S端收到后S端就知道自己与C端是可以连接成功的,但是C端此时并不知道S端是否接收到这个消息,所以S端接收到消息后得应答,C端得到S端的回复后,才能确定自己与S端是可以连接上的,这就是第二次握手。
  • C端只有确定了自己能与S端连接上才能开始发数据。所以两次握手肯定是最基本的。
  • 那么为什么需要第三次握手呢?假设一下如果没有第三次握手,而是两次握手后我们就认为连接建立,那么会发生什么?
  • 第三次握手是为了防止已经失效的连接请求报文段突然又传到服务端,因而产生错误
  • 具体情况就是:
  • C端发出去的第一个网络连接请求由于某些原因在网络节点中滞留了,导致延迟,直到连接释放的某个时间点才到达S端,这是一个早已失效的报文,但是此时S端仍然认为这是C端的建立连接请求第一次握手,于是S端回应了C端,第二次握手。
  • 如果只有两次握手,那么到这里,连接就建立了,但是此时C端并没有任何数据要发送,而S端就会傻傻的等待着,造成很大的资源浪费。所以需要第三次握手,只有C端再次回应一下,就可以避免这种情况。

5.3 四次握手断开连接

  • 如图所示: 

1.jpeg

  • 经过上面的建立连接图的解析,这个图应该不难看懂,这里主要有一个问题:为什么比建立连接时多了一次握手?
  • 可以看到这里服务端的ACK(回复客户端)和FIN(终止)消息并不是同时发出的,而是先ACK,然后再FIN,这也很好理解,当客户端要求断开连接时,此时服务端可能还有未发送完的数据,所以先ACK,然后等数据发送完再FIN。这样就变成了四次握手了。

赞赏支持


精彩留言

发表评论