网络和通信详解

news2024/12/4 15:47:34

一、Java 网络编程基础

  1. IP 地址和端口号
    • IP 地址
      • IP 地址是互联网协议地址,用于标识网络中的设备。在 Java 中,InetAddress类是用于表示 IP 地址的主要类。例如,InetAddress.getByName("www.example.com")可以获取指定域名对应的 IP 地址。IP 地址分为 IPv4(如192.168.0.1)和 IPv6(如2001:0db8:85a3:0000:0000:8a2e:0370:7334)两种格式。IPv4 地址由 32 位二进制数组成,通常用点分十进制表示;IPv6 地址由 128 位二进制数组成,用于提供更多的 IP 地址以满足不断增长的网络设备需求。
    • 端口号
      • 端口号是用于标识设备上的特定网络服务或应用程序的数字。它的取值范围是 0 - 65535,其中 0 - 1023 是系统保留端口,用于一些常见的网络服务,如 HTTP 服务通常使用端口 80,HTTPS 使用端口 443。在 Java 中,当创建网络应用程序时,需要指定一个端口号来让客户端能够找到并连接到服务端。例如,一个简单的 Web 服务器可能会在端口 8080 上监听客户端请求。
  2. 网络通信模型
    • OSI 模型和 TCP/IP 模型
      • OSI(开放式系统互联)模型是一个理论上的网络通信参考模型,分为七层,从下到上分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。而 TCP/IP 模型是实际应用更为广泛的网络通信模型,它分为四层,分别是网络接口层、网络层、传输层和应用层。在 Java 网络编程中,主要涉及的是传输层(如 TCP 和 UDP 协议)和应用层。
      • TCP/IP 模型的网络层主要负责处理 IP 数据包的寻址和路由,确保数据能够在不同的网络之间传输。传输层则提供端到端的通信服务,TCP 协议保证数据的可靠传输,UDP 协议提供快速但不可靠的传输。应用层是程序员直接接触的一层,在这里可以通过各种协议(如 HTTP、FTP 等)来构建网络应用程序。

二、基于 TCP 的 Java 网络编程

  1. Socket 和 ServerSocket 类
    • ServerSocket
      • ServerSocket是服务端用于监听客户端连接请求的类。当创建一个ServerSocket对象并指定一个端口号后,它就开始在该端口上监听。例如,ServerSocket serverSocket = new ServerSocket(8080);表示在端口 8080 上等待客户端连接。当有客户端请求连接时,可以通过serverSocket.accept()方法接受连接,这个方法会阻塞当前线程,直到有客户端连接成功,然后返回一个Socket对象用于和客户端进行通信。
    • Socket
      • Socket类代表一个客户端和服务端之间的连接。在客户端,可以通过Socket socket = new Socket("localhost", 8080);来创建一个连接到本地主机(localhost)的 8080 端口的连接。一旦连接建立,客户端和服务端就可以通过Socket对象获取输入流和输出流来进行数据的读写。例如,服务端可以通过InputStream inputStream = socket.getInputStream();获取客户端发送的数据输入流,通过OutputStream outputStream = socket.getOutputStream();向客户端发送数据。
  2. TCP 通信流程示例
    • 服务端流程
      • 首先创建ServerSocket对象并开始监听端口。
      • 当客户端连接请求到来时,接受连接并获取Socket对象。
      • 通过Socket对象获取输入流和输出流,读取客户端发送的数据并进行处理,然后将处理结果通过输出流发送回客户端。
      • 通信结束后,关闭SocketServerSocket对象。
    • 客户端流程
      • 创建Socket对象连接到服务端。
      • 获取输入流和输出流,将数据发送给服务端,并读取服务端返回的数据。
      • 通信结束后,关闭Socket对象。
  3. 应用场景和示例代码
    • 简单的文件传输服务端和客户端示例
      • 服务端代码
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class FileTransferServer {
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(8080);
            System.out.println("服务器正在等待客户端连接...");
            Socket socket = serverSocket.accept();
            System.out.println("客户端已连接");
            InputStream inputStream = socket.getInputStream();
            FileOutputStream fileOutputStream = new FileOutputStream("received_file.txt");
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer))!= -1) {
                fileOutputStream.write(buffer, 0, length);
            }
            System.out.println("文件接收成功");
            socket.close();
            serverSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 客户端代码
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

public class FileTransferClient {
    public static void main(String[] args) {
        try {
            Socket socket = new Socket("localhost", 8080);
            FileInputStream fileInputStream = new FileInputStream("source_file.txt");
            OutputStream outputStream = socket.getOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = fileInputStream.read(buffer))!= -1) {
                outputStream.write(buffer, 0, length);
            }
            System.out.println("文件发送成功");
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 在这个示例中,客户端将本地的source_file.txt文件发送给服务端,服务端接收文件并保存为received_file.txt。通过 TCP 协议的可靠传输保证文件内容的完整性。

三、基于 UDP 的 Java 网络编程

  1. DatagramSocket 和 DatagramPacket 类
    • DatagramSocket
      • DatagramSocket类用于发送和接收 UDP 数据包。在服务端和客户端都可以使用这个类。在服务端,可以使用DatagramSocket在指定端口监听 UDP 数据包;在客户端,可以使用它向指定的 IP 地址和端口发送 UDP 数据包。例如,DatagramSocket socket = new DatagramSocket();创建一个 UDP 套接字,用于发送和接收 UDP 数据包。
    • DatagramPacket
      • DatagramPacket类用于表示 UDP 数据包。它包含了要发送或接收的数据、数据的长度、目标 IP 地址和端口号(对于发送数据包)或者源 IP 地址和端口号(对于接收数据包)。例如,创建一个发送数据包可以使用byte[] data = "Hello".getBytes(); DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName("localhost"), 8080);,这里指定了要发送的数据为Hello,目标地址为本地主机的 8080 端口。
  2. UDP 通信流程示例
    • 服务端流程
      • 创建DatagramSocket对象并绑定到指定端口。
      • 创建DatagramPacket对象用于接收数据,通过DatagramSocketreceive方法接收数据包。
      • 处理接收到的数据,然后可以创建新的DatagramPacket对象将处理结果发送回客户端。
      • 通信结束后,关闭DatagramSocket对象。
    • 客户端流程
      • 创建DatagramSocket对象(如果不需要接收数据,也可以不创建)。
      • 创建DatagramPacket对象,将数据填充进去,通过DatagramSocketsend方法发送数据包给服务端。
      • 如果需要接收服务端返回的数据,可以创建接收数据包并使用receive方法接收。
      • 通信结束后,关闭DatagramSocket对象(如果创建了的话)。
  3. 应用场景和示例代码
    • 简单的 UDP 消息发送和接收示例
      • 服务端代码
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UDPServer {
    public static void main(String[] args) {
        try {
            DatagramSocket socket = new DatagramSocket(8080);
            byte[] buffer = new byte[1024];
            DatagramPacket receivePacket = new DatagramPacket(buffer, buffer.length);
            socket.receive(receivePacket);
            String message = new String(receivePacket.getData(), 0, receivePacket.getLength());
            System.out.println("收到消息: " + message);
            InetAddress clientAddress = receivePacket.getAddress();
            int clientPort = receivePacket.getPort();
            String response = "已收到你的消息";
            byte[] responseData = response.getBytes();
            DatagramPacket sendPacket = new DatagramPacket(responseData, responseData.length, clientAddress, clientPort);
            socket.send(sendPacket);
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 客户端代码
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UDPClient {
    public static void main(String[] args) {
        try {
            DatagramSocket socket = new DatagramSocket();
            String message = "你好";
            byte[] data = message.getBytes();
            InetAddress serverAddress = InetAddress.getByName("localhost");
            DatagramPacket packet = new DatagramPacket(data, data.length, serverAddress, 8080);
            socket.send(packet);
            byte[] buffer = new byte[1024];
            DatagramPacket receivePacket = new DatagramPacket(buffer, buffer.length);
            socket.receive(receivePacket);
            String response = new String(receivePacket.getData(), 0, receivePacket.getLength());
            System.out.println("收到回复: " + response);
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 在这个示例中,客户端向服务端发送一个简单的消息,服务端接收消息后发送一个回复给客户端。UDP 协议的快速性使得这种简单的消息交互能够快速完成,但不保证消息一定能完整和准确地到达。

四、高级网络编程主题

  1. 多线程在网络编程中的应用
    • 在网络编程中,尤其是服务端编程,为了能够同时处理多个客户端的连接请求,通常会使用多线程。例如,在基于 TCP 的服务端中,当接受一个客户端连接后,可以为这个客户端连接创建一个新的线程来处理后续的通信,这样服务端就可以继续监听其他客户端的连接请求,而不会因为一个客户端的长时间通信而阻塞。
    • 以下是一个简单的基于多线程的 TCP 服务端示例:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

class ClientHandler implements Runnable {
    private Socket socket;

    public ClientHandler(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer))!= -1) {
                String message = new String(buffer, 0, length);
                System.out.println("收到客户端消息: " + message);
                String response = "已收到你的消息";
                outputStream.write(response.getBytes());
            }
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public class MultiThreadedTCPServer {
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(8080);
            System.out.println("服务器正在等待客户端连接...");
            while (true) {
                Socket socket = serverSocket.accept();
                System.out.println("客户端已连接");
                Thread thread = new Thread(new ClientHandler(socket));
                thread.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 在这个示例中,ClientHandler类实现了Runnable接口,用于处理单个客户端的通信。在MultiThreadedTCPServermain方法中,每当有客户端连接时,就创建一个新的线程来运行ClientHandler,这样就可以同时处理多个客户端的通信。
  1. 网络安全相关概念(SSL/TLS)

    • SSL/TLS 简介
      • SSL(安全套接层)和 TLS(传输层安全)是用于在网络通信中提供安全加密的协议。它们可以保证数据在传输过程中的保密性、完整性和认证性。在 Java 中,可以通过javax.net.ssl包来实现 SSL/TLS 加密的网络通信。例如,在基于 TCP 的服务端和客户端通信中,可以使用 SSL/TLS 来加密传输的数据,防止数据被窃取或篡改。
    • 使用示例(简单介绍)
      • 首先需要创建密钥库(KeyStore)和信任库(TrustStore),用于存储服务器和客户端的证书、私钥等信息。然后在创建ServerSocketSocket对象时,通过SSLContext等相关类来配置 SSL/TLS 加密。具体的实现较为复杂,涉及到证书的生成、配置和管理等多个步骤,但这样可以为网络通信提供更高的安全性。
  2. Java 网络编程中的 NIO(非阻塞 I/O)

    • NIO 简介
      • Java NIO(New Input/Output)是一种非阻塞式的 I/O 操作方式,相比于传统的阻塞式 I/O,它可以在一个线程中同时处理多个通道(Channel)的 I/O 事件,提高了网络编程的效率。NIO 主要涉及三个核心组件:通道(Channel)、缓冲区(Buffer)和选择器(Selector)。
    • 核心组件介绍
      • 通道(Channel):通道类似于传统 I/O 中的流(Stream),但它是双向的,可以用于读写数据。在网络编程中,有SocketChannel(用于 TCP 通信)、DatagramChannel(用于 UDP 通信)等。例如,SocketChannel socketChannel = SocketChannel.open();可以打开一个 TCP 通道。
      • 缓冲区(Buffer):缓冲区是用于存储数据的容器,在 NIO 中,数据的读写都是通过缓冲区进行的。例如,ByteBuffer buffer = ByteBuffer.allocate(1024);创建了一个容量为 1024 字节的字节缓冲区。
      • 选择器(Selector):选择器用于监听多个通道的 I/O 事件,如连接就绪、读就绪、写就绪等。一个线程可以通过一个选择器来管理多个通道,当某个通道有 I/O 事件发生时,选择器会通知该线程进行处理。例如,Selector selector = Selector.open();创建一个选择器,然后可以将通道注册到选择器上,并设置感兴趣的 I/O 事件。
    • 简单示例(以 TCP 为例)
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class NIOServer {
    public static void main(String[] args) {
        try {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.bind(new InetSocketAddress(8080));
            serverSocketChannel.configureBlocking(false);
            Selector selector = Selector.open();
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            System.out.println("服务器正在等待客户端连接...");
            while (true) {
                selector.select();
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
                while (keyIterator.hasNext()) {
                    SelectionKey key = keyIterator.next();
                    if (key.isAcceptable()) {
                        ServerSocketChannel acceptedChannel = (ServerSocketChannel) key.channel();
                        SocketChannel socketChannel = acceptedChannel.accept();
                        socketChannel.configureBlocking(false);
                        socketChannel.register(selector, SelectionKey.OP_READ);
                    } else if (key.isReadable()) {
                        SocketChannel socketChannel = (SocketChannel) key.channel();
                        ByteBuffer buffer = ByteBuffer.allocate(1024);
                        int length = socketChannel.read(buffer);
                        if (length == -1) {
                            socketChannel.close();
                            key.cancel();
                        } else {
                            buffer.flip();
                            System.out.println("收到客户端消息: " + new String(buffer.array(), 0, length));
                            ByteBuffer responseBuffer = ByteBuffer.wrap("已收到你的消息".getBytes());
                            socketChannel.write(responseBuffer);
                        }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2253121.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【教学类-43-25】20241203 数独3宫格的所有可能-使用模版替换(12套样式,空1格-空8格,每套510张,共6120小图)

前期做数独惨宫格的所有排列&#xff0c;共有12套样式&#xff0c;空1格-空8格&#xff0c;每套510张&#xff0c;共6120小图&#xff09; 【教学类-43-24】20241127 数独3宫格的所有可能&#xff08;12套样式&#xff0c;空1格-空8格&#xff0c;每套510张&#xff0c;共6120…

Redis+Caffeine 多级缓存数据一致性解决方案

RedisCaffeine 多级缓存数据一致性解决方案 背景 之前写过一篇文章RedisCaffeine 实现两级缓存实战&#xff0c;文章提到了两级缓存RedisCaffeine可以解决缓存雪等问题也可以提高接口的性能&#xff0c;但是可能会出现缓存一致性问题。如果数据频繁的变更&#xff0c;可能会导…

echarts地图立体效果,echarts地图点击事件,echarts地图自定义自定义tooltip

一.地图立体效果 方法1:两层地图叠加 实现原理:geo数组中放入两个地图对象,通过修改zlevel属性以及top,left,right,bottom形成视觉差 配置项参考如下代码: geo: [{zlevel: 2,top: 96,map: map,itemStyle: {color: #091A51ee,opacity: 1,borderWidth: 2,borderColor: #16BAFA…

D87【python 接口自动化学习】- pytest基础用法

day87 pytest运行参数 -m -k 学习日期&#xff1a;20241203 学习目标&#xff1a;pytest基础用法 -- pytest运行参数-m -k 学习笔记&#xff1a; 常用运行参数 pytest运行参数-m -k pytest -m 执行特定的测试用例&#xff0c;markers最好使用英文 [pytest] testpaths./te…

总结拓展十七:特殊采购业务——委外业务

SAP中委外采购业务&#xff0c;又称供应商分包&#xff08;或外协、转包、、外包、托外等&#xff09;&#xff0c;是企业将部分生产任务委托给外部供应商/集团其他分子公司完成的一种特殊采购业务模式。 委外业务主要有2大类型&#xff0c;分别是标准委外&#xff08;委外采购…

ESP8266作为TCP客户端或者服务器使用

ESP8266模块&#xff0c;STA模式&#xff08;与手机搭建TCP通讯&#xff0c;EPS8266为服务端&#xff09;_esp8266作为station-CSDN博客 ESP8266模块&#xff0c;STA模式&#xff08;与电脑搭建TCP通讯&#xff0c;ESP8266 为客户端&#xff09;_esp8266 sta 连接tcp-CSDN博客…

ATTCK红队评估实战靶场(四)

靶机链接&#xff1a;http://vulnstack.qiyuanxuetang.net/vuln/detail/6/ 环境搭建 新建两张仅主机网卡&#xff0c;一张192.168.183.0网段&#xff08;内网网卡&#xff09;&#xff0c;一张192.168.157.0网段&#xff08;模拟外网网段&#xff09;&#xff0c;然后按照拓补…

C 语言 “神秘魔杖”—— 指针初相识,解锁编程魔法大门(一)

文章目录 一、概念1、取地址操作符&#xff08;&&#xff09;2、解引用操作符&#xff08;*&#xff09;3、指针变量1、 声明和初始化2、 用途 二、内存和地址三、指针变量类型的意义1、 指针变量类型的基本含义2、 举例说明不同类型指针变量的意义 四、const修饰指针1、co…

封装loding加载动画的请求

图片 /*** Loading 状态管理类*/ export class Loading {constructor(timer300) {this.value falsethis.timer timer}/*** 执行异步操作并自动管理 loading 状态* param {Promise|Function|any} target - Promise、函数或其他值* returns {Promise} - 返回请求结果*/async r…

人形机器人训练、机器臂远程操控、VR游戏交互、影视动画制作,一副手套全部解决!

广州虚拟动力基于自研技术推出了多节点mHand Pro动捕数据手套&#xff0c;其最大的特点就是功能集成与高精度捕捉&#xff0c;可以用于人形机器人训练、机器臂远程操控、VR游戏交互、影视动画制作等多种场景。 一、人形机器人训练 mHand Pro动捕数据手套双手共装配16个9轴惯性…

Nginx Web服务器管理、均衡负载、访问控制与跨域问题

Nginx Web 服务器的均衡负载、访问控制与跨域问题 Nginx 的配置 1. 安装Nginx 首先安装Nginx apt install nginx -ycaccpurgatory-v:~$ sudo apt install nginx [sudo] password for cacc: Reading package lists... Done Building dependency tree... Done Reading state i…

Bert+CRF的NER实战

CRF&#xff08;条件随机场-Conditional Random Field&#xff09; 原始本文&#xff1a;我在北京吃炸酱面 标注示例&#xff08;采用BIO标注方式&#xff09;&#xff1a; 我O在O北B-PLA京I-PLA吃O炸B-FOOD酱I-FOOD面I-FOOD CRF&#xff1a; 目的&#xff1a;提出一些不可能…

C++语法·识

人生建议&#xff1a;请手机反省一下&#xff0c;为什么总拉着我熬夜。 目录 STL简介 string类容器一 auto&#xff08;自动声明类型&#xff09; 简介&#xff1a; 特点 范围for&#xff08;语法糖&#xff09; 简介 特点 string string类的常见接口 1.构造 2.容…

蓝桥杯准备训练(lesson1,c++方向)

前言 报名参加了蓝桥杯&#xff08;c&#xff09;方向的宝子们&#xff0c;今天我将与大家一起努力参赛&#xff0c;后序会与大家分享我的学习情况&#xff0c;我将从最基础的内容开始学习&#xff0c;带大家打好基础&#xff0c;在每节课后都会有练习题&#xff0c;刚开始的练…

【开源】A059-基于SpringBoot的社区养老服务系统的设计与实现

&#x1f64a;作者简介&#xff1a;在校研究生&#xff0c;拥有计算机专业的研究生开发团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看项目链接获取⬇️&#xff0c;记得注明来意哦~&#x1f339; 赠送计算机毕业设计600个选题ex…

winform跨线程更新界面

前言&#xff1a; 大家好&#xff0c;我是上位机马工&#xff0c;硕士毕业4年年入40万&#xff0c;目前在一家自动化公司担任软件经理&#xff0c;从事C#上位机软件开发8年以上&#xff01;我们在开发C#程序的时候&#xff0c;有时候需要在非Ui主线程更新界面&#xff0c;为了…

无界(wujie)微前端项目搭建,nginx线上部署,pnpm一键安装依赖、启动应用,git代码仓库存放方式

这里写自定义目录标题 1. 创建项目项目目录布局选择主应用子应用 2. pnpm包管理&#xff0c;一键安装、启动、打包pnpm一键安装依赖npm-run-all 一键启动、打包 3. nginx线上部署主应用中子应用中nginx文件目录及配置 git代码存放方式 1. 创建项目 主应用&#xff1a; vue3vit…

10.容器-list列表

定义一个list使用[] 定义一个空列表 [] 或者 list() 列表中每个元素之间用逗号隔开 a_list [aa, bb, cc] print(a_list) # <class list> print(type(a_list)) list列表可以存储不同类型的元素 a_list [aa, bb, cc] print(a_list) # <class list> print(type…

BiGRU:双向门控循环单元在序列处理中的深度探索

一、引言 在当今的人工智能领域&#xff0c;序列数据的处理是一个极为重要的任务&#xff0c;涵盖了自然语言处理、语音识别、时间序列分析等多个关键领域。循环神经网络&#xff08;RNN&#xff09;及其衍生结构在处理序列数据方面发挥了重要作用。然而&#xff0c;传统的 RN…

PDF与PDF/A的区别及如何使用Python实现它们之间的相互转换

目录 概述 PDF/A 是什么&#xff1f;与 PDF 有何不同&#xff1f; 用于实现 PDF 与 PDF/A 相互转换的 Python 库 Python 实现 PDF 转 PDF/A 将 PDF 转换为 PDF/A-1a 将 PDF 转换为 PDF/A-1b 将 PDF 转换为 PDF/A-2a 将 PDF 转换为 PDF/A-2b 将 PDF 转换为 PDF/A-3a 将…