网络编程

发布时间 2023-09-09 11:54:27作者: SimpleWord
title: 网络编程
index_img: https://tuchuangs.com/imgs/2023/08/12/aa149ca851821467.png
tags:
  - Java SE
categories:
  - Java SE
excerpt: 网络编程

网络编程:计算机之间通过网络传输数据。

软件架构

image-20230812193018157

image-20230812193223368

image-20230812193318942

网络编程三要素

IP

  • 上网设备在网络中的地址,是唯一的。
  • 127.0.0.1永远表示当前设备的IP
  • ipconfig:查看本机ip
  • ping +ip/域名:检查网络是否畅通

InetAddress类可以获得IP对象,它的子类包含IPv4和IPv5相关。

方法 描述
static InetAddress getByName(String host) 确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址
String getHostName() 获取此IP地址的主机名
String getHostAddress() 返回文本显示中的IP地址字符串
public class Main {
    public static void main(String[] args) throws UnknownHostException {
        InetAddress address = InetAddress.getByName("shyfvm"); //获取IP对象
        String hostAddress = address.getHostAddress();
        String hostName = address.getHostName();

        System.out.println(hostAddress); 
        System.out.println(hostName);
    }
}

image-20230812195124553

端口号

  • 应用在设备中的标识

  • 由两个字节表示的整数,取值范围:0~65535

    • 其中0~1023之间的端口号用于一些知名的网络服务或者应用。
    • 我们自己使用1024以上的端口号就可以了。

一个端口号,只能被一个应用程序使用。【反之不成立】

协议

  • 数据的传输规则。常见的有:UDPTCPhttphttpsftp

image-20230812195853816

image-20230812200005062

UDP

  • 速度快
  • 有大小限制一次最多发送64K
  • 数据不安全,易丢失数据
  • 面向无连接:不需要先建立连接,直接发送

发送数据

不用建立连接,也不管是否发送成功

步骤 说明
找快递公司 创建发送端的DatagramSocket对象
打包礼物 准备要发送的数据,并可能需要将数据转换为某种格式(例如字节数组)以进行发送
数据打包(DatagramPacket) 创建DatagramPacket对象,将你的数据放入其中
快递公司发送包裹 使用DatagramSocket对象的send方法发送DatagramPacket对象
付钱走人 释放 DatagramSocket 资源
public class Main {
    public static void main(String[] args) throws Exception {
        //可以指定端口号,也可以不指定【自己找】
        DatagramSocket ds = new DatagramSocket(9999); //发送方对象

        String msg = "Hello ,I am SimpleWord!"; //数据
        byte[] bytes = msg.getBytes();

        InetAddress address = InetAddress.getByName("127.0.0.1"); //指定接收方的ip和端口
        int port = 9090;

        ////参数是byte数组,包含多种重载方法【数据、发送长度、ip、端口】
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port); //打包

        ds.send(dp);
    }
}

接收数据

必须指定接收数据的端口(且必须是数据发送到接口才能接收到)

步骤 说明
找快递公司 创建接收端的DatagramSocket对象
接收箱子 接收打包好的数据
从箱子里面获取礼物 解析接收到的数据包
签收走人 释放 DatagramSocket 资源
public class Main {
    public static void main(String[] args) throws IOException {
        //接收方对象
        DatagramSocket ds = new DatagramSocket(9090); //必须指定

        //接收数据包
        byte[] bytes = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
        ds.receive(dp);  //此方法是阻塞方法,只有接收到了才会继续执行

        //解析数据包【包含数据、数据长度、】
        byte[] data = dp.getData(); //就是上方哪个数组现在的数据【可能没用完】
        int length = dp.getLength(); //接收到的长度
        InetAddress fromAddress = dp.getAddress(); //获取发送端的ip
        int port = dp.getPort(); //获取发送方的端口

        //释放资源
        ds.close();

        System.out.println("数据:"+new String(data,0,length));
        System.out.println("数据来自:"+fromAddress+",端口:"+port);
    }
}

image-20230812203448518

UDP三种通信方式

单播

  • 就是上方代码,1对1

组播

image-20230812204156690

  • 组内的设备可接收
public class Main {
    public static void main(String[] args) throws Exception {
        MulticastSocket mu= new MulticastSocket(9999);

        String message ="组播";
        byte[] bytes =message.getBytes("UTF-8");

        InetAddress address = InetAddress.getByName("224.0.0.1");
        int port =9090;

        DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);

        mu.send(dp);

        mu.close();
    }
}
public class Main {
    public static void main(String[] args) throws IOException {
        MulticastSocket mu = new MulticastSocket();

        //将当前主机添加到224.0.0.1这1组中
        InetAddress address = InetAddress.getByName("224.0.0.1");
        mu.joinGroup(address);

        byte[] bytes = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
        mu.receive(dp);

        byte[] data = dp.getData();
        int length = dp.getLength();
        InetAddress fromAddress = dp.getAddress();
        int port = dp.getPort();

        mu.close();

        System.out.println("数据:" + new String(data, 0, length));
        System.out.println("数据来自:" + fromAddress + ",端口:" + port);
    }
}

image-20230812210002057

广播

image-20230812204226073

  • 局域网内所有设备都可以接收到,单播的发送地址修改为广播即可

image-20230812210336989

TCP

  • 面向连接的:需要先建立连接才能发送
  • 速度慢
  • 没有大小限制
  • 数据安全。【三次握手、四次挥手】

代码实现

image-20230812210715707

IO流来自Socket通信,只需要关闭Socket即可关闭流。

public class Main {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9090); //必须一样,可以理解为同一个通道
        Socket accept = serverSocket.accept(); //阻塞的,等待客户端
        InputStream in = accept.getInputStream(); //从提到中获得输出流
        /*
         可以使用转换流、缓冲流提高效率
        */
        byte[] bytes = new byte[1024];
        int b;
        while ((b = in.read(bytes)) != -1) {
            System.out.print(new String(bytes, 0, b, "UTF-8")); //防止乱码
        }
        serverSocket.close();
        accept.close();
    }
}
public class Main {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("127.0.0.1",9090);//对应服务器的accept等到客服端
        OutputStream out = socket.getOutputStream(); //从连接通道中获取IO流
        out.write("你好,my name is java!".getBytes());
        socket.close();
    }
}

image-20230812213105308

三次握手

保证TCP连接的建立

image-20230812213738464

四次挥手

断开连接,并保证数据传输完成

image-20230812213835357