Обмен технологиями

Ключевые знания Java для продвинутых пользователей-23-Сетевое программирование

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Введение в сетевое программирование

структура программного обеспечения

  • Структура C/S: полное название — структура «клиент/сервер», которое относится к структуре клиента и сервера.
  • Структура B/S: полное имя — структура браузера/сервера, которое относится к структуре браузера и сервера.

Протокол сетевой связи

网络通信协议:通信协议是对计算机必须遵守的规则,只有遵守这些规则,计算机之间才能进行通信。

  • Протокол TCP/IP: Протокол управления передачей/Интернет-протокол (Протокол управления передачей/Интернет-протокол),
    Самый простой и распространенный протокол Интернета.
    Вставьте сюда описание изображения

Классификация протоколов

java.net 包中提供了两种常见的网络协议的支持

  1. TCP: протокол управления передачей. Протокол TCP представляет собой протокол связи, ориентированный на соединение, то есть перед передачей данных между отправляющей стороной и принимающей стороной устанавливается логическое соединение, а затем данные передаются. Он обеспечивает надежную и безошибочную передачу данных между двумя сторонами. компьютеры.
  2. UDP: протокол пользовательских датаграмм. Протокол UDP — это протокол без установления соединения. При передаче данных нет необходимости устанавливать соединение. Независимо от того, запущена ли служба другой стороны, данные, источник данных и пункт назначения непосредственно инкапсулируются в пакет данных и отправляются напрямую. Размер каждого пакета ограничен 64 КБ. Это ненадежный протокол, поскольку соединение отсутствует, поэтому скорость передачи высокая, но данные легко теряются.

Трехстороннее рукопожатие в TCP: В протоколе TCP на этапе подготовки отправки данных между клиентом и сервером происходит три взаимодействия для обеспечения надежности соединения.

  • При первом рукопожатии клиент отправляет серверу запрос на соединение и ожидает подтверждения от сервера.
  • При втором рукопожатии сервер отправляет ответ клиенту, уведомляя его о получении запроса на соединение.
  • При третьем рукопожатии клиент снова отправляет на сервер подтверждающую информацию для подтверждения соединения.

Три элемента сетевого программирования

  1. Протокол: правила, которым должна подчиняться связь в компьютерной сети.
  2. IP-адрес: относится к адресу интернет-протокола, обычно известному как IP. IP-адреса используются для уникальной нумерации компьютерных устройств в сети.
  • IPv4: это 32-битное двоичное число, обычно разделенное на 4 байта, выраженное в форме abcd, например 192.168.65.100. Среди них a, b, c и d — все десятичные целые числа от 0 до 255, поэтому можно представить до 4,2 миллиарда.
  • Используя длину адреса 128 бит, каждая группа из 16 байт делится на 8 групп шестнадцатеричных чисел, выраженных как ABCD:EF01:2345:6789:ABCD:EF01:2345:6789, что решает проблему нехватки ресурсов сетевых адресов. .
    Часто используемые команды:
  • ipconfig [Просмотр локального IP-адреса]
    Вставьте сюда описание изображения
  • Пропингуйте IP-адрес пространства [проверьте, подключена ли сеть]
  1. Номер порта
  • Целое число, представленное двумя байтами, диапазон его значений: 0 ~ 65535.Среди них номера портов от 0 до 1023 используются некоторыми известными сетями.
    Сетевые службы и приложения, обычные приложения должны использовать номера портов выше 1024. Если номер порта занят другой службой или приложением, текущая программа не запустится.
    Определить процессы в сети: 协议 + IP地址 + 端口号

TCP-программа связи

TCP通信能实现两台计算机之间的数据交互,通信的两端,要严格区分为客户端(Client)与服务端(Server)。

Этапы коммуникации

  • Серверную программу необходимо запустить заранее и ждать подключения клиента.
  • Клиент активно подключается к серверу и может общаться только в случае успешного соединения. Сервер не может активно подключаться к клиенту.

В Java предусмотрены два класса для реализации программ связи TCP:

  1. Клиент: представлен классом java.net.Socket. Создайте объект Socket, отправьте запрос на соединение на сервер, сервер ответит на запрос, и они оба установят соединение и начнут связь.
  2. Сервер: представлен классом java.net.ServerSocket. Создание объекта ServerSocket эквивалентно запуску службы и ожиданию подключения клиента.

Класс сокета

Socket 类:该类实现客户端套接字,套接字指的是两台设备之间通讯的端点。
Метод строительства:
public Socket(String host, int port) : Создает объект сокета и подключает его к указанному номеру порта на указанном хосте. Если указанный хост имеет значение NULL, это эквивалентно тому, что указанный адрес является адресом обратной связи (Адрес обратной связи (127.xxx) — это локальный адрес обратной связи (адрес обратной связи).)。
Методы члена:

  • public InputStream getInputStream() : Возвращает входной поток для этого сокета.
  • public OutputStream getOutputStream() : Возвращает выходной поток для этого сокета.
  • public void close() : Закройте этот сокет.
  • public void shutdownOutput() : отключает выходной поток для этого сокета.

Класс ServerSocket

ServerSocket 类:这个类实现了服务器套接字,该对象等待通过网络的请求。
Метод строительства:
public ServerSocket(int port): используйте этот конструктор, чтобы привязать его к указателю при создании объекта ServerSocket.
Для определенного номера порта параметр port является номером порта.
Методы члена:
public Socket accept() : прослушивать и принимать соединения, а также возвращать новый объект Socket для связи с клиентом.Этот метод
Будет блокироваться до тех пор, пока не будет установлено соединение.

Простая сетевая программа TCP

Анализ TCP-связи:

  1. [Сервер] Запустите, создайте объект ServerSocket и дождитесь подключения.
  2. [Клиент] Запустите, создайте объект Socket и запросите соединение.
  3. [Сервер] получает соединение, вызывает метод принятия и возвращает объект Socket.
  4. [Клиент] Объект сокета получает OutputStream и записывает данные на сервер.
  5. [Сервер] Объект сокета получает входной поток и считывает данные, отправленные клиентом.
  6. [Сервер] Объект сокета получает OutputStream и записывает данные обратно клиенту.
  7. [Клиент] Объект Scoket получает входной поток, анализирует и записывает данные.
  8. [Клиент] Освободите ресурсы и отключитесь.

Пример кода:

  • Сервис-Терминал:
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerTCP {
    public static void main(String[] args) throws IOException {
        System.out.println("服务端启动 , 等待连接 .... ");
        // 1.创建 ServerSocket对象,绑定端口,开始等待连接
        ServerSocket ss = new ServerSocket(6666);
        // 2.接收连接 accept 方法, 返回 socket 对象.
        Socket server = ss.accept();
        // 3.通过socket 获取输入流
        InputStream is = server.getInputStream();
        // 4.一次性读取数据
        // 4.1 创建字节数组
        byte[] b = new byte[1024];
        // 4.2 据读取到字节数组中.
        int len = is.read(b);
        // 4.3 解析数组,打印字符串信息
        String msg = new String(b, 0, len);
        System.out.println(msg);
        //5.关闭资源.
        is.close();
        server.close();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

Сервер указывает номер порта, получает объект Socket с помощью метода Accept(), получает входной поток через клиентский объект и, наконец, считывает данные и ожидает сообщения, отправленного клиентом.

  • клиент
import java.net.Socket;

public class ClientTCP {
    public static void main(String[] args) throws Exception {
        System.out.println("客户端 发送数据");
        // 1.创建 Socket ( ip , port ) , 确定连接到哪里.
        Socket client = new Socket("localhost", 6666);
        // 2.获取流对象 . 输出流
        OutputStream os = client.getOutputStream();
        // 3.写出数据.
        os.write("你好么? tcp ,我来了".getBytes());
        // 4. 关闭资源 .
        os.close();
        client.close();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

При создании клиента укажите IP-адрес и номер порта соединения, чтобы облегчить подключение к серверу, получите выходной поток и выведите данные через клиентский объект Socket.
Вставьте сюда описание изображения

Загрузка файла [Расширенный]

  1. [Клиент] Входной поток, чтение данных файла с жесткого диска в программу.
  2. [Клиент] Выходной поток, запись данных файла на сервер.
  3. [Сервер] Входной поток, чтение данных файла в серверную программу.
  4. [Сервер] Выходной поток, запись данных файла на жесткий диск сервера.
  5. [Сервер] Получите выходной поток и запишите данные обратно.
  6. [Клиент] Получите входной поток, проанализируйте и запишите данные обратно.

数据准备:Поместите файл с именем test.jpg на диск D и создайте тестовую папку.

Пример кода:

  • Сервер
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class FileUpload_Server {
    public static void main(String[] args) throws IOException {
        System.out.println("服务器 启动..... ");
        // 1. 创建服务端ServerSocket
        ServerSocket serverSocket = new ServerSocket(6666);
        // 2. 循环接收,建立连接
        while (true) {
        Socket accept = serverSocket.accept();
            /* 3. socket对象交给子线程处理,进行读写操作Runnable接口中,只有一个run方法,使用lambda表达式简化格式 */
            new Thread(() -> {
                try (   //3.1 获取输入流对象
                        BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());
                        //3.2 创建输出流对象, 保存到本地 .
                        FileOutputStream fis = new FileOutputStream("D:/test/" + System.currentTimeMillis() + ".jpg");
                        BufferedOutputStream bos = new BufferedOutputStream(fis)) {
                    // 3.3 读写数据
                    byte[] b = new byte[1024 * 8];
                    int len;
                    while ((len = bis.read(b)) != -1) {
                        bos.write(b, 0, len);
                    }

                    // 4.=======信息回写===========================
                    System.out.println("back ........");
                    OutputStream out = accept.getOutputStream();
                    out.write("上传成功".getBytes());
                    out.close();

                    //5. 关闭 资源
                    bos.close();
                    bis.close();
                    accept.close();
                    System.out.println("文件上传已保存");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

Здесь мы сначала создаем объект сервера, используем while(true) для обеспечения непрерывного соединения с сервером, а затем запускаем поток, чтобы гарантировать, что когда пользователь загружает большой файл, это не повлияет на эффективность загрузки файлов другими пользователями. Используйте системные миллисекунды + «.jpg», чтобы установить имя файла, чтобы гарантировать, что имя файла не будет перезаписано из-за того же имени файла во время загрузки.

  • клиент
import java.io.*;
import java.net.Socket;

public class FileUpload_Client {
    public static void main(String[] args) throws IOException {
        // 1.创建流对象
        // 1.1 创建输入流,读取本地文件
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\test.jpg"));
        // 1.2 创建输出流,写到服务端
        Socket socket = new Socket("localhost", 6666);
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        //2.写出数据.
        byte[] b = new byte[1024 * 8 ];
        int len ;
        while (( len = bis.read(b))!=-1) {
            bos.write(b, 0, len);
        }
        // 关闭输出流,通知服务端,写出数据完毕
        socket.shutdownOutput();
        System.out.println("文件发送完毕");   
        // 3. =====解析回写============
        InputStream in = socket.getInputStream();
        byte[] back = new byte[20];
        in.read(back);
        System.out.println(new String(back));
        in.close();
        // ============================
        // 4.释放资源
        socket.close();
        bis.close();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

Вставьте сюда описание изображения
Вставьте сюда описание изображения
Здесь мы видим, что наш сервер успешно сохранил отправленный пользователем файл на жесткий диск.

Любители Java могут ознакомиться с этой статьей. Автор продолжит ее обновлять и с нетерпением ждет вашего внимания и коллекции. . .