java-网络编程-UDP,TCP通信

基本通信架构

  • CS架构(Client客户端/Server服务端)
  • BS架构(Browser浏览器/Server服务端)

网络通信三要素

IP地址

常用命令:

ipconfig:查看本机IP地址

ping IP地址:检查网络是否连通

InetAddress

代表IP地址
常用方法

java 复制代码
public class InetAddressDemo1 {
    public static void main(String[] args) {
        //InetAddress获取本机IP对象和对方IP对象
        try {
            //1、获取本机IP对象
            InetAddress local = InetAddress.getLocalHost();
            System.out.println(local);
            System.out.println(local.getHostName());
            System.out.println(local.getHostAddress());
            //2、获取对方IP对象
            InetAddress remote = InetAddress.getByName("www.mihoyo.com");
            System.out.println(remote.getHostName());
            System.out.println(remote.getHostAddress());
            //3、判断IP地址是否可达
            boolean reachable = remote.isReachable(5000);
            System.out.println(reachable);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

端口

计算机内部标记应用程序的序号,范围0-65535

  • 分类
    周知端口:0-1023,被预定义的知名应用占用
    注册端口:1024-49151,分配给应用程序和用户进程
    动态端口:49152-65535,动态分配

协议

UDP(用户数据报协议):无连接,不可靠

数据按照包发

java提供了java.net.DatagramSocket类实现UDP通信

  • 一发一收
java 复制代码
public class UPDClientDemo1 {
    public static void main(String[] args) throws Exception {
        System.out.println("客户端启动了...");
        //UPD通信一发一收:客户端
        //1、创建发送端对象
        DatagramSocket socket = new DatagramSocket();
        //2、创建数据包对象,封装数据
        byte[] data = "UPD通信一发一收".getBytes();
        /**
         * public DatagramPacket(byte[] buf, int length, InetAddress address, int port)
         * 参数一:数据,字节数组
         * 参数二:数据长度
         * 参数三:指定接收端的IP地址
         * 参数四:指定接收端的端口号
         */
        DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getLocalHost(), 10086);

        //3、发送端对象发送数据包的数据
        socket.send(packet);
    }
}
java 复制代码
public class UPDServerDemo2 {
    public static void main(String[] args) throws Exception {
        System.out.println("服务端启动了...");
        //UPD通信一发一收:服务端
        //1、创建接收端对象,注册端口
        DatagramSocket socket = new DatagramSocket(10086);

        //2、创建数据包对象,接收数据
        byte[] buf = new byte[1024 * 64];
        DatagramPacket packet = new DatagramPacket(buf, buf.length);

        //3、接收数据
        socket.receive(packet);

        //4、解析数据
        //获取当前接收到的数据长度
        int length = packet.getLength();
        String data = new String(buf, 0, length);
        System.out.println("服务端收到数据:" + data);

        //获取对方IP对象和程序端口
        String ip = packet.getAddress().getHostAddress();
        int port = packet.getPort();
        System.out.println("对方IP:" + ip + ",端口:" + port);

    }
}
  • 多发多收
java 复制代码
public class UPDServerDemo2 {
    public static void main(String[] args) throws Exception {
        System.out.println("服务端启动了...");
        //UPD通信多发多收:服务端
        //1、创建接收端对象,注册端口
        DatagramSocket socket = new DatagramSocket(10086);

        //2、创建数据包对象,接收数据
        byte[] buf = new byte[1024 * 64];
        DatagramPacket packet = new DatagramPacket(buf, buf.length);

        while (true) {
            //3、接收数据
            socket.receive(packet);//阻塞式接收数据

            //4、解析数据
            //获取当前接收到的数据长度
            int length = packet.getLength();
            String data = new String(buf, 0, length);
            System.out.println("服务端收到数据:" + data);

            //获取对方IP对象和程序端口
            String ip = packet.getAddress().getHostAddress();
            int port = packet.getPort();
            System.out.println("对方IP:" + ip + ",端口:" + port);

            System.out.println("----------------");
        }
    }
}
java 复制代码
public class UPDClientDemo1 {
    public static void main(String[] args) throws Exception {
        System.out.println("客户端启动了...");
        //UPD通信多发多收:客户端
        //1、创建发送端对象
        DatagramSocket socket = new DatagramSocket();
        DatagramPacket packet = null;

        Scanner sc = new Scanner(System.in);

        while (true) {
            System.out.println("请输入要发送的数据:");
            String data = sc.nextLine();

            //若输入exit则退出
            if ("exit".equals(data)) {
                System.out.println("客户端退出了...");
                socket.close();
                break;
            }

            //2、创建数据包对象,封装数据
            byte[] bytes = data.getBytes();
            packet = new DatagramPacket(bytes, bytes.length, InetAddress.getLocalHost(), 10086);

            //3、发送端对象发送数据包的数据
            socket.send(packet);
        }
    }
}

TCP(传输控制协议):面向连接,可靠通信

java提供了java.net.Socket类实现TCP通信

  • 一发一收
    客户端
java 复制代码
public class ClientDemo1 {
    public static void main(String[] args) throws Exception {
        //TCP通信下一发一收:客户端
        //1、创建socket管道对象,请求与服务端的socket链接,可靠连接
        Socket socket = new Socket("127.0.0.1", 10086);

        //2、从socket通信管道中得到字节输出流
        OutputStream os = socket.getOutputStream();

        //3、特殊数据流
        DataOutputStream dos = new DataOutputStream(os);
        dos.writeInt(1);
        dos.writeUTF("嗨,想我了吗?");

        //4、关闭管道
        socket.close();
    }
}

服务端

服务端是通过java.net包下的ServerSocket类实现的

java 复制代码
public class ServerDemo2 {
    public static void main(String[] args) throws Exception {
        System.out.println("服务端启动了...");
        //TCP通信一发一收:服务端
        //1、创建服务端ServerSocket对象,注册端口
        ServerSocket server = new ServerSocket(10086);
        //2、调用accept方法,阻塞等待客户端连接,一旦有客户端连接,返回Socket对象
        Socket socket = server.accept();
        //3、获取输入流,读取数据
        InputStream is = socket.getInputStream();
        //4、把字节输入流包装成特殊数据输入流
        DataInputStream dis = new DataInputStream(is);
        //5、读取数据
        int id = dis.readInt();
        String msg = dis.readUTF();
        System.out.println("id:" + id + ",收到消息:" + msg);
        //6、客户端ip和端口
        System.out.println("客户端IP:" + socket.getInetAddress().getHostAddress());
        System.out.println("客户端端口:" + socket.getPort());
    }
}
  • 多发多收
java 复制代码
public class ClientDemo1 {
    public static void main(String[] args) throws Exception {
        System.out.println("客户端启动了...");
        //TCP通信下多发多收:客户端
        //1、创建socket管道对象,请求与服务端的socket链接,可靠连接
        Socket socket = new Socket("127.0.0.1", 10086);

        //2、从socket通信管道中得到字节输出流
        OutputStream os = socket.getOutputStream();

        //3、特殊数据流
        DataOutputStream dos = new DataOutputStream(os);

        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请输入:");
            String msg = sc.nextLine();
            if ("exit".equals(msg)) {
                System.out.println("886,程序退出...");
                socket.close();
                break;
            }
            dos.writeUTF(msg);
            dos.flush();
        }
    }
}
java 复制代码
public class ServerDemo2 {
    public static void main(String[] args) throws Exception {
        System.out.println("服务端启动了...");
        //TCP通信多发多收:服务端
        //1、创建服务端ServerSocket对象,注册端口
        ServerSocket server = new ServerSocket(10086);
        //2、调用accept方法,阻塞等待客户端连接,一旦有客户端连接,返回Socket对象
        Socket socket = server.accept();
        //3、获取输入流,读取数据
        InputStream is = socket.getInputStream();
        //4、把字节输入流包装成特殊数据输入流
        DataInputStream dis = new DataInputStream(is);
        while (true) {
            //5、读取数据
            String msg = dis.readUTF();
            System.out.println("收到消息:" + msg);
            //6、客户端ip和端口
            System.out.println("客户端IP:" + socket.getInetAddress().getHostAddress());
            System.out.println("客户端端口:" + socket.getPort());
            System.out.println("-------------------------");
        }
    }
}

服务端支持多个客户端同时连接

java 复制代码
public class ServerDemo2 {
    public static void main(String[] args) throws Exception {
        System.out.println("服务端启动了...");
        //TCP通信多发多收:服务端,支持多个客户端连接
        //1、创建服务端ServerSocket对象,注册端口
        ServerSocket server = new ServerSocket(10086);
        while (true) {
            //2、调用accept方法,阻塞等待客户端连接,一旦有客户端连接,返回Socket对象
            Socket socket = server.accept();
            //3、把这个客户端管道交给一个独立的子线程专门负责接收这个管道的消息
            new ServerReader(socket).start();
        }
    }
}
java 复制代码
public class ServerReader extends  Thread{
    private Socket socket;
    public ServerReader(Socket socket) {
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            InputStream is = socket.getInputStream();
            DataInputStream dis = new DataInputStream(is);
            while (true) {
                String msg = dis.readUTF();
                System.out.println("客户端:" + msg);
                //客户端ip和端口
                System.out.println("客户端ip:" + socket.getInetAddress().getHostAddress());
                System.out.println("客户端端口:" + socket.getPort());
            }
        } catch (Exception e) {
            System.out.println("客户端下线了" + socket.getInetAddress().getHostAddress());
        }
    }
}
相关推荐
lkbhua莱克瓦241 小时前
Java基础——常用API2
java·笔记·github·学习方法
摇滚侠1 小时前
Spring Boot3零基础教程,Lambda 表达式与函数式接口,笔记95
java·spring boot·笔记
2501_938791831 小时前
Rust Axum 框架开发后端服务:实现高性能 TCP 连接的处理逻辑
网络·tcp/ip·rust
好学且牛逼的马1 小时前
【JavaWeb|day19 Web后端进阶 SpringAOP、SpringBoot原理、自定义Starter、Maven高级】
java·spring boot·rpc
码界奇点1 小时前
Java 开发日记MySQL 与 Redis 双写一致性策略挑战与实战解析
java·redis·sql·mysql·java-ee
GHZero1 小时前
Java 之解读String源码(九)
java·开发语言
Swift社区1 小时前
Lombok 不生效 —— 从排查到可运行 Demo(含实战解析)
java·开发语言·安全
南清的coding日记1 小时前
Java 程序员的 Vue 指南 - Vue 万字速览(01)
java·开发语言·前端·javascript·vue.js·css3·html5
@大迁世界2 小时前
我用 Rust 重写了一个 Java 微服务,然后丢了工作
java·开发语言·后端·微服务·rust
自在极意功。2 小时前
Java static关键字深度解析
java·开发语言·面向对象·static