TCP和UDP数据传输方式

IP概念

IP地址,唯一标识网络中的每一台计算机,32位,由4个8位二进制数组成。

IP地址=网络地址+主机地址,网络地址:表示计算机或网络设备所在的网段,主机地址:标识特定主机或网络设备。

请添加图片描述
计算机上不同的应用程序通过不同的端口来与其它计算机通信,端口范围0-65535,系统保留端口0-1023

java程序中通常用localhost表示本机,即127.0.0.1

Socket

套接字=IP地址+端口,java中使用Socket类来封装套接字信息,例如:如果IP地址是210.37.145.1,而端口号是23,那么得到套接字就是(210.37.145.1:23)。所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。
套接字是通信的基石,是支持TCP/IP协议的路通信的基本操作单元。

TCP

全称:Transfer Control Protocal

  • 传输控制协议
  • 面向端对端连接的可靠性传输协议
  • 确认两端建立可靠连接后才开始通信
  • 为了确保可靠性,丧失了部分性能
  • 三次握手
  • 与打电话相似

OSI模型

图示

TCP/IP协议

请添加图片描述
数据传输由TCP/IP分层模型中的传输层负责,该层包含TCP和UDP两种协议

TCP协议

  • 较可靠的双向流协议
  • 发送任意数量的数据
  • 提供消息确认、错误检测和错误恢复等服务

UDP协议

  • 比较不可靠

基于TCP方式实现客户端服务端数据传输

客户端:

  1. 创建客户端Socket对象
  2. 指定服务端的IP+端口号
  3. 编写准备发送的数据
  4. 创建输出流对象,通过Socket对象调用方法
  5. 通过输出流写入准备发送的数据
  6. 关闭Socket资源、关闭流对象
package TCP;

import java.io.*;
import java.net.Socket;

/**
 * Created with IntelliJ IDEA.
 * User: Santo
 * Date: 2022/03/13 10:01
 * Description: 客户端:通过java.net.Socket对象发送数据
 * Version: V1.0
 */
public class Client {
    
    
    private static final String Server_IP = "127.0.0.1";//服务器IP地址
    private static final int Server_PORT = 8087;//服务器端口号
    public static void main(String[] args) throws IOException {
    
    
        //1.创建Socket对象
        Socket socket = new Socket(Server_IP,Server_PORT);
        //2.准备要发送的数据
        String say = "hello";
        //3.创建输出流对象
        OutputStream os = socket.getOutputStream();
        //4.将字节流转换为字符流
        Writer writer = new OutputStreamWriter(os);
        BufferedWriter bf = new BufferedWriter(writer);
        System.out.println("客户端发送的数据:" +say);
        //5.向流中写入数据
        bf.write(say);
        bf.flush();

        //禁用此套接字的输出流
        socket.shutdownOutput();

        //接收来自服务器的回复
        //3.创建输入流对象,通过监听的socket对象调用
        InputStream is = socket.getInputStream();
        //4.将字节流转换成字符流
        Reader reader = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(reader);
        //5. 输出客户端发送的数据
        String serverData = br.readLine();
        System.out.println("客户端接收到服务端的数据:" + serverData);


        //6.关闭资源
        bf.close();
        socket.close();
    }
}

服务端:

  1. 创建服务端的ServerSocket对象(指定端口号)
  2. 监听来自客户端请求Socket对象
  3. 创建输入流对象,通过监听Socket对象调用
  4. 通过输入流读取客户端发送的数据
  5. 关闭ServerSocket资源,关闭流资源
package TCP;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Created with IntelliJ IDEA.
 * User: Santo
 * Date: 2022/03/13 10:39
 * Description:
 * Version: V1.0
 */
public class Server {
    
    
    private static final int Server_PORT = 8087;//服务器IP地址
    public static void main(String[] args) throws IOException {
    
    
        //1.创建ServerSocket对象
        ServerSocket serverSocket = new ServerSocket(Server_PORT);//创建绑定到指定端口的服务器套接字。
        //2.监听客户端请求
        Socket socket = serverSocket.accept();//监听要连接到此套接字并接收它。
        //3.创建输入流对象,通过监听的socket对象调用。
        InputStream is = socket.getInputStream();
        //4.将字节流转换成字符流操作
        Reader reader = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(reader);
        //5.输出客户端发出的数据
        String clientData = br.readLine();
        System.out.println("服务端接收到客户端的数据:" + clientData);


        //禁用此套接字的输入流
        socket.shutdownInput();


        //服务端回复消息给客户端
        String replySay = "Santo,Santo";
        OutputStream os = socket.getOutputStream();
        //4.将字节流转换成字符流
        Writer writer = new OutputStreamWriter(os);
        BufferedWriter bf = new BufferedWriter(writer);
        System.out.println("服务端回复的消息:" + replySay);
        bf.write(replySay);
        bf.flush();
        bf.close();

        //6.关闭资源
        br.close();
        //关闭socket
        socket.close();
        serverSocket.close();
    }
}

先运行Server端才能运行Client端
结果:
在这里插入图片描述
在这里插入图片描述

基于UDP方式实现数据传输

1.创建一个足够大的字节数组,用于存储要接收的包的数据

2.使用该字节数组实例化一个DatagramPacket对象

3.DatagramSocket被实例化,它被指定该套接字要绑定到的本地主机上的一个端口

4.调用DatagramSocket类的receive()方法,将DatagramPacket对象传入该方法。这将导致执行线程阻塞,直到接收到一个数据报包或者发生了超时

package UDP;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

/**
 * Created with IntelliJ IDEA.
 * User: Santo
 * Date: 2022/03/13 16:12
 * Description:
 * Version: V1.0
 */
public class Boy {
    
    
    public static final String Girl_HOST = "127.0.0.1";
    public static final int Girl_Port = 8087;
    public static void main(String[] args) throws Exception {
    
    
        //信息
        String say = "我喜欢你!";
        byte[] boySay = say.getBytes();
        //女生地址
        InetAddress inetAddress = InetAddress.getByName(Girl_HOST);
        //构造用于发送长度的分组的数据报包 length指定主机上到指定的端口号
        DatagramPacket dp = new DatagramPacket(boySay,0,boySay.length,inetAddress,Girl_Port);
        //创建一个用于接收或者发送的DatagramSocket ——发射器
        DatagramSocket ds = new DatagramSocket();
        //发送数据包
        ds.send(dp);

        byte[] by = new byte[1024];
        DatagramPacket dp2 = new DatagramPacket(by,0,by.length);
        //从此套接字接收数据报包
        ds.receive(dp2);
        //拆包
        byte[] girlSay = dp2.getData();
        String girlSayStr = new String(girlSay);
        System.out.println("男孩收到女孩的回信:" + girlSayStr);
    }
}

package UDP;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;
import java.net.SocketException;

/**
 * Created with IntelliJ IDEA.
 * User: Santo
 * Date: 2022/03/13 16:12
 * Description:
 * Version: V1.0
 */
public class Girl {
    
    
    private static final int Girl_Port = 8087;
    public static void main(String[] args) throws IOException {
    
    
        //创建一个用于接收或者发送的DatagramSocket ——接收器
        DatagramSocket ds = new DatagramSocket(Girl_Port);
        byte[] bys = new byte[1024];
        //接收数据包——拆包
        DatagramPacket dp = new DatagramPacket(bys,0,bys.length);
        //接收-按照如上方法拆包
        ds.receive(dp);
        //拆包
        byte[] boySay = dp.getData();
        String boySayStr = new String(boySay);
        System.out.println(boySayStr);

        //回复
        String girlSay = "我也喜欢你!";
        byte[] gs = girlSay.getBytes();
        //得到发送端地址
        SocketAddress sa = dp.getSocketAddress();
        DatagramPacket dp2 = new DatagramPacket(gs,gs.length,sa);
        ds.send(dp2);
    }
}

同理,先运行女生端,这里是把女生端当作服务器端
结果:
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/shadowburn1ng/article/details/123464193