首页 > 编程语言 >Java基础——网络编程

Java基础——网络编程

时间:2024-11-16 15:50:41浏览次数:3  
标签:Java socket 编程 网络 System println new public 服务端

  1. 可以让设备中的程序与网络上其他设备中的程序进行数据交互(实现网络通信的)。

1. 基本的通信架构

  1. 基本的通信架构有2种形式:CS架构(Client客户端/Server服务端)、BS架构(Browser浏览器/Server服务端)
  2. 无论CS架构,还是BS架构的软件都必须依赖网络编程

2. 网络通信的三要素

2.1. IP

  1. 全称互联网协议地址,是设备在网络中的地址,是唯一的标识。
2.1.1. IP地址的形式
  1. IPv4(32位,点分十进制表示)
  2. IPv6(128位,分成8段表示,每段每四位编码成一个十六进制位表示,每段中间用:隔开)
2.1.2. 公网IP、内网IP
  1. 公网IP:是可以连接互联网的IP地址
  2. 内网IP:也叫局域网IP,只能组织或机构内部使用
  3. 192.168.开头的就是常见的局域网地址,范围为192.168.0.0-192.168.255.255,专门为组织机构内部使用
  4. 127.0.0.1、localhost代表本机,只会寻找当前所在的主机。
2.1.3. 常用命令
  1. ipconfig:查看本机IP地址
  2. ping IP地址:检查网络是否连通
2.1.4. InetAddress

代表IP地址

2.2. 端口

  1. 应用程序在设备中唯一的标识
  2. 是一个16位的二进制,范围是0~65535
2.2.1. 分类
  1. 周知端口:0~1023,内预先定义的知名应用占用(如,HTTP占用80,FTP占用21)
  2. 注册端口:1024~49151,分配给用户进程或某些应用程序
  3. 动态端口:49151~65535,一般不固定分配给某种进程,而是动态分配
  4. 我们自己开发的程序一般选择注册端口,且一个设备中不能出现两个程序的端口号一样,否则出错

2.3. 协议

  1. 网络中的通信设备,事先规定的连接规则,以及传输数据的规则被称为网络通信协议。
2.3.1. 网络模型

2.3.2. UDP协议
  1. 用户数据报协议
  2. 无连接、不可靠通信
  3. 通信效率高,适合语音通话、视频直播等
2.3.3. TCP协议
  1. 传输控制协议
  2. 面向连接、可靠通信
  3. 目的是要保证在不可靠的信道上实现可靠的传输
  4. 三个步骤实现可靠通信:三次握手建立连接,传输数据进行确认,四次挥手断开连接。
  5. 可靠连接:客户端和服务器都能发送和接收数据,全双工
  6. 通信效率相对不高,但可靠,适用于网页、文件下载、支付等

3. UDP通信

  1. Java提供了一个java.net.DatagramSocket类来实现UDP通信。

3.1. 提供方法

3.2. 一发一收

public class Client {
    public static void main(String[] args) throws IOException {
        // 1. 创建客户端对象
        DatagramSocket socket = new DatagramSocket();

        // 2. 创建数据包对象, 封装要发的数据
        /*
        参数一 要发送的数据的字节数组
        参数二 要发送数据的字节数
        参数三 目标服务端地址
        参数四 目标服务端端口
         */
        byte[] bytes = "我是客户端, 123".getBytes();
        DatagramPacket packet = new DatagramPacket(bytes, bytes.length, InetAddress.getLocalHost(), 6666);

        // 3. 开始发送数据到服务端
        socket.send(packet);

        System.out.println("客户端发送数据完毕");
        socket.close(); // 释放系统资源
    }
}
public class Server {
    public static void main(String[] args) throws Exception {
        // 1. 创建一个服务端对象 并注册端口
        DatagramSocket server = new DatagramSocket(6666);
        // 2. 创建数据包对象 用于接收数据
        byte[] buffer = new byte[1024 * 64]; // 64kb
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

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

        // 4. 将接收的数据输出 接收多少 输出多少
        System.out.println(new String(buffer, 0, packet.getLength()));

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

    }
}

3.3. 多发多收

public class Client {
    public static void main(String[] args) throws IOException {
        // 1. 创建客户端对象
        DatagramSocket socket = new DatagramSocket();

        // 2. 创建数据包对象, 封装要发的数据
        /*
        参数一 要发送的数据的字节数组
        参数二 要发送数据的字节数
        参数三 目标服务端地址
        参数四 目标服务端端口
         */
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("请说");
            String s = scanner.nextLine();
            byte[] bytes = s.getBytes();

            if("exit".equals(s)){
                socket.close();
                System.out.println("退出成功");
                break;
            }

            DatagramPacket packet = new DatagramPacket(bytes, bytes.length, InetAddress.getLocalHost(), 6666);

            // 3. 开始发送数据到服务端
            socket.send(packet);
        }

    }
}
public class Server {
    public static void main(String[] args) throws Exception {
        // 1. 创建一个服务端对象 并注册端口
        DatagramSocket server = new DatagramSocket(6666);
        // 2. 创建数据包对象 用于接收数据
        byte[] buffer = new byte[1024 * 64]; // 64kb
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

        while (true) {
            // 3. 接收数据
            server.receive(packet);

            // 4. 将接收的数据输出 接收多少 输出多少
            System.out.println(new String(buffer, 0, packet.getLength()));

            // 5. 获取客户端主机名 和 端口
            System.out.println(packet.getAddress().getHostAddress());
            System.out.println(packet.getPort());
            System.out.println("-----------------------------");
        }


    }
}

4. TCP通信

  1. Java提供了一个java.net.Socket类来实现TCP通信

4.1. 客户端

public class Client {
    public static void main(String[] args) throws Exception {
        // 1. 创建一个Socket对象 请求与服务端进行连接
        Socket socket = new Socket(InetAddress.getLocalHost(), 8888);

        // 2. 获取输出流 向服务端发送数据
        OutputStream outputStream = socket.getOutputStream();

        // 3. 使用高级流包装原始流
        DataOutputStream dataOutputStream = new DataOutputStream(outputStream);

        // 4. 向服务端发送数据
        dataOutputStream.writeUTF("你好, 我是客户端");

        dataOutputStream.close(); // 释放资源
        socket.close();
    }
}

4.2. 服务端

  1. 服务端是通过java.net.ServerSocket类来实现的。

public class Server {
    public static void main(String[] args) throws Exception {
        // 1. 创建ServerSocket对象, 并指名端口号
        ServerSocket serverSocket = new ServerSocket(8888);

        // 2. 使用accept方法, 等待客户端的连接请求
        Socket socket = serverSocket.accept();

        // 3. 获取字节输入流
        InputStream inputStream = socket.getInputStream();

        // 4. 包装成数据输入流
        DataInputStream dataInputStream = new DataInputStream(inputStream);

        // 5. 读取客户端发来的数据
        String s = dataInputStream.readUTF();
        System.out.println(s);

        // 释放资源
        dataInputStream.close();
        socket.close();
    }
}

4.3. 多发多收

  1. 客户端
public class Client {
    public static void main(String[] args) throws Exception {
        // 1. 创建一个Socket对象 请求与服务端进行连接
        Socket socket = new Socket(InetAddress.getLocalHost(), 8888);

        // 2. 获取输出流 向服务端发送数据
        OutputStream outputStream = socket.getOutputStream();

        // 3. 使用高级流包装原始流
        DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("请说");
            String s = scanner.nextLine();
            if("exit".equals(s)){
                dataOutputStream.close(); // 释放资源
                socket.close();
                System.out.println("退出成功");
                break;
            }
            // 4. 向服务端发送数据
            dataOutputStream.writeUTF(s);
            dataOutputStream.flush();
        }
    }
}
  1. 服务端
public class Server {
    public static void main(String[] args) throws Exception {
        // 1. 创建ServerSocket对象, 并指名端口号
        ServerSocket serverSocket = new ServerSocket(8888);

        // 2. 使用accept方法, 等待客户端的连接请求
        Socket socket = serverSocket.accept();

        // 3. 获取字节输入流
        InputStream inputStream = socket.getInputStream();

        // 4. 包装成数据输入流
        DataInputStream dataInputStream = new DataInputStream(inputStream);

        while (true) {
            try {
                // 5. 读取客户端发来的数据
                String s = dataInputStream.readUTF();
                System.out.println(s);
            } catch (Exception e) {
                System.out.println(socket.getRemoteSocketAddress() + "离线了");
                dataInputStream.close();
                socket.close();
                break;
            }
        }
    }
}

4.4. 实现与多个客户端同时通信

  1. 上述的服务端程序是不支持与多个客户端同时通信的,因为服务端现在只有一个主线程,只能处理一个客户端的消息。
  2. 可以通过多线程实现与多个客户端的同时通信

客户端

public class Client {
    public static void main(String[] args) throws Exception {
        // 1. 创建一个Socket对象 请求与服务端进行连接
        Socket socket = new Socket(InetAddress.getLocalHost(), 8888);

        // 2. 获取输出流 向服务端发送数据
        OutputStream outputStream = socket.getOutputStream();

        // 3. 使用高级流包装原始流
        DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("请说");
            String s = scanner.nextLine();
            if("exit".equals(s)){
                dataOutputStream.close(); // 释放资源
                socket.close();
                System.out.println("退出成功");
                break;
            }
            // 4. 向服务端发送数据
            dataOutputStream.writeUTF(s);
            dataOutputStream.flush();
        }
    }
}

服务端

public class Server {
    public static void main(String[] args) throws Exception {
        // 1. 创建ServerSocket对象, 并指名端口号
        ServerSocket serverSocket = new ServerSocket(8888);

        while (true) {
            // 2. 使用accept方法, 等待客户端的连接请求
            Socket socket = serverSocket.accept();
            System.out.println("有人上线了" + socket.getRemoteSocketAddress());

            // 3. 将这个客户端对应的Socket管道交给独立的线程处理
            new ServerReaderThread(socket).start();

        }


    }
}

自定义线程

public class ServerReaderThread extends Thread{
    private Socket socket;
    public ServerReaderThread(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            // 1. 获取字节输入流
            InputStream inputStream = this.socket.getInputStream();
            // 2. 使用高级流进行封装
            DataInputStream dataInputStream = new DataInputStream(inputStream);

            while (true){
                // 3. 读取信息
                try {
                    String s = dataInputStream.readUTF();
                    System.out.println(s);
                } catch (IOException e) {
                    System.out.println("有人下线了" + socket.getRemoteSocketAddress());
                    dataInputStream.close();
                    socket.close();
                    break;
                }
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

4.5. TCP通信实现BS架构

  1. 服务端
public class Server {
    public static void main(String[] args) throws Exception {
        // 1. 创建ServerSocket对象, 并指名端口号
        ServerSocket serverSocket = new ServerSocket(8080);

        while (true) {
            // 2. 使用accept方法, 等待浏览器的连接请求
            Socket socket = serverSocket.accept();
            System.out.println("有人上线了" + socket.getRemoteSocketAddress());

            // 3. 将这个浏览器对应的Socket管道交给独立的线程处理
            new ServerReaderThread(socket).start();

        }


    }
}
  1. 自定义线程
public class ServerReaderThread extends Thread{
    private Socket socket;
    public ServerReaderThread(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {
        // 处理浏览器请求, 返回一个你好,666
        try {
            OutputStream outputStream = socket.getOutputStream();
            PrintStream printStream = new PrintStream(outputStream);
            printStream.println("HTTP/1.1 200 OK");
            printStream.println("Content-Type:text/html;charset=UTF-8");
            printStream.println(); // 必须换行
            printStream.println("<h1>你好, 666</h1>");
            printStream.close();
            socket.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}
  1. 使用线程池优化
public class Server {
    public static void main(String[] args) throws Exception {
        // 1. 创建ServerSocket对象, 并指名端口号
        ServerSocket serverSocket = new ServerSocket(8080);

        // 创建线程池
        ThreadPoolExecutor pool = new ThreadPoolExecutor(8 * 2, 8 * 2, 0,
                TimeUnit.SECONDS, new ArrayBlockingQueue<>(8), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());


        while (true) {
            // 2. 使用accept方法, 等待浏览器的连接请求
            Socket socket = serverSocket.accept();
            System.out.println("有人上线了" + socket.getRemoteSocketAddress());

            // 3. 将这个浏览器对应的Socket管道交给独立的线程处理
            // 创建Runnable任务对象
            ServerReaderRunnable runnable = new ServerReaderRunnable(socket);
            pool.execute(runnable);

        }


    }
}

标签:Java,socket,编程,网络,System,println,new,public,服务端
From: https://blog.csdn.net/weixin_68853331/article/details/143818578

相关文章

  • Java基础——多线程
    1.线程是一个程序内部的一条执行流程程序中如果只有一条执行流程,那这个程序就是单线程的程序2.多线程指从软硬件上实现的多条执行流程的技术(多条线程由CPU负责调度执行)2.1.如何创建多条线程Java通过java.lang.Thread类的对象来代表线程2.1.1.方式一:继承Thread类//1......
  • 深入了解内容分发网络(CDN)
    在当今的电商、直播、社交工具和视频网站等互联网应用中,存在着大量的图片、视频、文档等资源需要分发给用户。对于一些体量较大的应用而言,若将大量资源集中在单一节点进行分发,几乎没有哪个机房能够承受如此巨大的流量。例如,一个日活达100W的小型互联网产品,若每次请求需1M......
  • 哋它亢编程语言3.13版本:新时代的编程艺术?
    在技术的浪潮中,总有一些创新让我们眼前一亮。今天,我们要探索的是“哋它亢编程语言”3.13版本(参考:https://datacon-14302.xyz/3.13/),这个版本带来了一系列令人振奋的新特性和改进,让我们的编程体验更上一层楼。哋它亢3.13:新时代的编程艺术“哋它亢”一直以其简洁的语法和强大的功能......
  • 哋它亢编程语言3.14.0a1版本:性能与易用性的双重飞跃
    在这个快速变化的技术时代,编程语言也在不断地进化。“哋它亢编程语言”3.14.0a1版本带来了一系列令人兴奋的新特性和改进,这些改进不仅提升了性能,也增强了易用性。(参考:https://datacon-14302.xyz/3.14/)让我们深入探讨这个新版本的一些亮点。性能优化:延迟评估注解根据PEP649,3.......
  • Java-面向对象(下)
    下面让我们继续学习面向对象类的继承在现有类的基础上去构建一个新的类。现有类叫做基类(baseclass)、超类(superclass)新的类叫做派生类(derivedclass)、子类(孩子类)(childclass)如果一个类想要继承另外一个类,需要用到extends关键字。class基类{}class子类extends......
  • 20222406 2024-2025-1 《网络与系统攻防技术》实验五实验报告
    202224062024-2025-1《网络与系统攻防技术》实验五实验报告1.实验内容对网站进行DNS域名查询,包括注册人、IP地址等信息,还通过相关命令查询IP地址注册人及地理位置。尝试获取QQ好友IP地址并查询其地理位置。使用nmap对靶机环境扫描,获取靶机IP活跃状态、开......
  • 20222310 2024-2025-1 《网络与系统攻防技术》实验六实验报告
    一、实验内容学习掌握Metasploit工具的使用。下载靶机Metasploitable2,完成以下实验内容。1.前期渗透(1)主机发现(可用Aux中的arp_sweep,search一下就可以use)(2)端口扫描(可以直接用nmap,也可以用Aux中的portscan/tcp等)(3)扫描系统版本,漏洞等2.Vsftpd源码包后门漏洞(21端口)3.SambaMS-R......
  • 20222423 2024-2025-1 《网络与系统攻防技术》实验六实验报告
    1.实验内容1.1内容回顾总结总而言之这周都重点在于Metasploit工具的使用时间上,对其功能和使用流程有了深入了解,也越发感叹道魔高一尺,道高一丈,好多漏洞如今的操作系统或者软件都已经修复,通过msf针对漏洞实施变得越发困难(重点点名本周的msf测试作业,让我一天都没吃上饭,基本上时间......
  • “哋它亢”编程语言:开启编程新纪元
    在技术日新月异的今天,编程语言的选择对于开发者来说至关重要。今天,我要向大家介绍一款新兴的编程语言——“哋它亢”。这门语言以其独特的优势,正在成为软件开发领域的新宠。语言简介:“哋它亢”是一门易于学习、功能强大的编程语言。它以其优雅的语法和动态类型系统,为开发者提供......
  • #Java-面向对象进阶-1
    1.static静态属性static是Java中的一个修饰符,可用来修饰成员变量、成员方法a.静态变量被static修饰的成员变量称为静态变量静态变量被该类的所有成员共享调用方式:类名调用(推荐)对象名调用例:创建方法//在创建的类中:publicstaticStringname;调用:假设类为:Stud......