Java 网络编程基础

网络通信三要素

此笔记来之与黑马.B站的视频是真的高

基本的通信架构

  • 基本的通信架构有2种形式:CS架构(Client 客户端/ Server 服务端)、BS架构( Browser 浏览器/ Server 服务端)。

image-20241005174021564

IP 地址

IP(InternetProtocol):全称 “互联网协议地址”,是分配给上网设备的唯一标志。
IP 地址有两种形式:IPv4, IPv6

image-20241005174700193

image-20241005174812691

image-20241005175206940

image-20241005175323233

⚠️ 右上角框框为 运营商 id

公网 IP, 内网 IP
  • **公网 IP:**是可以连接互联网的 IP 地址;内网 IP:也叫局域网 IP,只能组织机构内部使用。
  • 192.168.开头的就是常见的局域网地址,范围即为 192.168.0.0–192.168.255.255,专门为组织机构内部使用。
特殊 IP 地址:
  • 127.0.0.1、localhost:代表本机 IP,只会寻找当前所在的主机。
IP 常用命令:
  • ipconfig:查看本机IP地址。
  • ping IP地址:检查网络是否连通。
InnetAddress (IP 地址)

image-20241005175829937

端口号

标记正在计算机设备上运行的应用程序的,被规定为一个 16位 的二进制,范围是 0 ~ 65535。

分类
  • 周知端口:0 ~ 1023,被预先定义的知名应用占用(如:HTTP占用80,FTP占用21)

  • **注册端口:**1024 ~ 49151,分配给用户进程或某些应用程序。

  • 动态端口:49152 到 65535,之所以称为动态端口,是因为它一般不固定分配某种进程,而是动态分配。

    ⚠️ 注意:我们自己开发的程序一般选择使用注册端口,且一个设备中不能出现两个程序的端口号一样,否则出错。

通信协议

网络上通信的设备,事先规定的连接规则,以及传输数据的规则被称为网络通信协议。

image-20241005190510717

开放式网络互联标准:OSI 网络参考模型
  • OSI 网络参考模型:全球网络互联标准

image-20241005190553340

传输层的2个通信协议
  • UDP(User Datagram Protocol):用户数据报协议;TCP(Transmission Control Protocol):传输控制协议。
UDP协议

特点:无连接、不可靠通信。诵信效率高!语音诵话视频直播

  • 不事先建立连接,数据按照包发,一包数据包含:自己的 IP、程序端口,目的地 IP、程序端口和数据(限制在 64KB 内)等。
  • 发送方不管对方是否在线,数据在中间丢失也不管,如果接收方收到数据也不返回确认,故是不可靠的。

image-20241005191313754

TCP 协议
  • 特点:面向连接、可靠通信。
  • TCP 的最终目的:要保证在不可靠的信道上实现可靠的传输。
  • TCP 主要有三个步骤实现可靠传输:三次握手建立连接,传输数据进行确认,四次挥手断开连接。

image-20241005191628265

四次挥手

image-20241005191731199

ContentsUDP通信-快速入门

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

image-20241005192053753

public class Client {public static void main(String[] args) throws Exception {// 1. 创建客户对象(发数据出去的人)DatagramSocket socket = new DatagramSocket();// 2. 创建数据包对象封装要发出去的数据(创建一个数据包)/** public DatagramPacket(byte buf[], int length,InetAddress address, int port)参数一: 封装要发出去的数据参数二:发送出去的数据大小(字节个数)参数三:服务端的 IP 地址(找到服务端主机)参数四:服务端程序的端口*/byte[] byres = "我是快乐的客户端,我爱你 abc".getBytes();DatagramPacket packet = new DatagramPacket(bytes, bytets.length,InetAddress.getLocalHost(), port: 6666);// 3. 正式发送这个数据包的数据出去了socket.send(packet);System.out.println("客户端数据发送完毕~~");socket.close(); // 释放数据!}
}class Server {public static void main(Stirng[] args) throws Exception {System.out.println("-----服务器端启动");// 1. 创建一个服务端口(创建一个接数据包的人) 注册端口DatagramSocker socket = new DatagramSocket(port: 6666);// 2. 创建一个数据包对象,用于接收数据的(创建一个数据包)byte[] buffer = new byte[1024 * 64]; // 64 KBDatagramPacket packet = new DatagramPacket(buffer.length);// 3. 开始正式使用数据包来接收客户端发来的数据socket.receive(packet);// 4.从字节数组中,把接收到的数据直接打印出来// 接收多少就倒出多少int len = packet.getLength();String res = new String(buffer, 0, len);System.out.println(rs);System.out.println(packet.getAddress().getHostAddresss());System.out.prinlnt(packet.getPort());socket.close(); //释放资源}
}

UDP 通信-多发多收

public class Client {public static void main(String[] args) throws Exception {// 1. 创建客户对象(发数据出去的人)DatagramSocket socket = new DatagramSocket();// 2. 创建数据包对象封装要发出去的数据(创建一个数据包)/** public DatagramPacket(byte buf[], int length,InetAddress address, int port)参数一: 封装要发出去的数据参数二:发送出去的数据大小(字节个数)参数三:服务端的 IP 地址(找到服务端主机)参数四:服务端程序的端口*/Scanner scanner = new Scanner(System.in);while (true) {System.out.println("请说: ");String msg = scanner.nextLine();if ("exit".equals(msg)) {break;}byte[] byres = msg.getBytes();DatagramPacket packet = new DatagramPacket(bytes, bytets.length,InetAddress.getLocalHost(), port: 6666);// 3. 正式发送这个数据包的数据出去了socket.send(packet);System.out.println("客户端数据发送完毕~~");}socket.close(); // 释放数据!}
}class Server {public static void main(Stirng[] args) throws Exception {System.out.println("-----服务器端启动");// 1. 创建一个服务端口(创建一个接数据包的人) 注册端口DatagramSocker socket = new DatagramSocket(port: 6666);// 2. 创建一个数据包对象,用于接收数据的(创建一个数据包)byte[] buffer = new byte[1024 * 64]; // 64 KBDatagramPacket packet = new DatagramPacket(buffer.length);while (true) {System.out.println("服务端启动");// 3. 开始正式使用数据包来接收客户端发来的数据socket.receive(packet);// 4.从字节数组中,把接收到的数据直接打印出来// 接收多少就倒出多少int len = packet.getLength();String res = new String(buffer, 0, len);System.out.println(rs);System.out.println(packet.getAddress().getHostAddresss());System.out.printtln(packet.getPort());   System.out.println("--------------分割线---------------");}socket.close(); //释放资源}
}

TCP 通信-快速入门

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

image-20241005200654684

image-20241005200740292

public class Client {public static void main(String[] args) throws Exception {// 1. 创建 Socket 对象,并同时请求与服务端程序的连接Socket socket = new Socket("127.0.0.1", 8888);// 2.从 socket 通信管道中得到一个字节输出流,用来发数据给服务端程序OutputStream os = socket.getOutputStream();// 3.把低级的字节输出流包装成数据输出流DataOutputStream dos = new DataOutputStream(os);// 4.开始写数据出去了dos.writeUTF("在一起, 好吗?");dos.close();socket.close(); // 释放连接资源}
}public class Server {public static void main(String[] args) {}
}

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

image-20241005201852781

public class Server {public static void (String[] args) throws Exception {// 1. 创建 ServerSocket的对象, 同时为服务器注册端口ServerSocket serverSocket = new ServerSocket(port: 8888);// 2.使用 serverSocket 对象,调用一个 accept 方法,等待客户端的连接请求Socket socket = serverSocket.accept();// 3. 从socket通信管道中得到一个字节输入流InputStream is = socket.getInputStream();// 5.使用数据输入流读取客户端发送过来的消息String rs = dis.readUTF();System.out.println(rs);System.out.println(socket.getRemoteSocketAddress())dis.close();socket.close();}
}

TCP 通信-多发多收

public class Client {public static void main(String[] args) throws Exception {// 1. 创建 Socket 对象,并同时请求与服务端程序的连接Socket socket = new Socket("127.0.0.1", 8888);// 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();// 一旦用户输入了 exit, 就退出了客户端程序if ("exit".equals(msg)) {System.out.println("欢迎您下次光临!! 退出成功!");break;}// 4.开始写数据输出了dos.writeUTF(msg);dos.flush();}dos.close();socket.close(); // 释放连接资源}
}
public class Server {public static void (String[] args) throws Exception {// 1. 创建 ServerSocket的对象, 同时为服务器注册端口ServerSocket serverSocket = new ServerSocket(port: 8888);// 2.使用 serverSocket 对象,调用一个 accept 方法,等待客户端的连接请求Socket socket = serverSocket.accept();// 3. 从socket通信管道中得到一个字节输入流InputStream is = socket.getInputStream();// 4.把原始的字节输入流包装成数据输入流DataInputStream dis = new DataInputStream(is);while (true) {// 5.使用数据输入流读取客户端发送过来的消息try {String rs = dis.readUTF();System.out.println(rs);} catch (Exception e) {e.printStackTrace();System.out.println(socket.getRemoteSocketAddress() + "离线了");break;}}dis.close();socket.close();}
}

TCP 通信-同时接收多个客户端

image-20241005205708921

public class Client {public static void main(String[] args) throws Exception {// 1. 创建 Socket 对象,并同时请求与服务端程序的连接Socket socket = new Socket("127.0.0.1", 8888);// 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();// 一旦用户输入了 exit, 就退出了客户端程序if ("exit".equals(msg)) {System.out.println("欢迎您下次光临!! 退出成功!");break;}// 4.开始写数据输出了dos.writeUTF(msg);dos.flush();}dos.close();socket.close(); // 释放连接资源}
}

public class Server {public static void main(String[] args) {System.out.println("--------服务器启动成功--------------");// 1. 创建ServerSocket的对象,同时为服务端注册端口ServerSocket serverSocket = new ServerSocket(8888);while (true) {// 2. 使用serverSocket对象,调用一个 accept 方法,等待客户端连接请求Socket socket = serverSocket.accept();// 3. 把这个客户端对应的socket通信管道,交给一个独立的线程负责处理new ServerReaderThread(socket).start();}}
}
public class ServerReaderThread extends Thread {private Socket socket;public ServerReaderThread(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {InputStream is = socket.getInputStream();DataInputStream dis = new DataInputStream(is);while (true) {String msg = dis.readUTF();System.out.println(msg);}} catch (IOException e) {e.printStackTrace();}}
}

TCP通信-综合案例

即时通信-群聊

image-20241005211636643

public class Client {public static void main(String[] args) throws Exception {// 1. 创建 Socket 对象,并同时请求与服务端程序的连接Socket socket = new Socket("127.0.0.1", 8888);// 创建一个独立的线程 负责随机从socket中接收服务端发送过来的消息new ClentReaderThread(socket).start();// 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();// 一旦用户输入了 exit, 就退出了客户端程序if ("exit".equals(msg)) {System.out.println("欢迎您下次光临!! 退出成功!");break;}// 4.开始写数据输出了dos.writeUTF(msg);dos.flush();}dos.close();socket.close(); // 释放连接资源}@Overridepublic void run() {try {InputStream is = socket.getInputStream();DataInputStream dis = new DataInputStream(is);while (true) {try {String msg = dis.readUTF();System.out.println(msg);} catch (Exception e) {System.out.println("自己下线了: " + socket.getRemoteSock());}}}}
}
public class ClentReaderThread extends Thread {private Socket socket;public ClentReaderThread(Socket socket) {this.socket = socket;}
}

public class Server {public static List<Socket> onLineSockets = new ArrayList<>();public static void main(String[] args) {System.out.println("--------服务器启动成功--------------");// 1. 创建ServerSocket的对象,同时为服务端注册端口ServerSocket serverSocket = new ServerSocket(8888);while (true) {// 2. 使用serverSocket对象,调用一个 accept 方法,等待客户端连接请求Socket socket = serverSocket.accept();onLineSockets.add(socket); 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;}@Overridepublic void run() {try {InputStream is = socket.getInputStream();DataInputStream dis = new DataInputStream(is);while (true) {String msg = dis.readUTF();System.out.println(msg);sendMsgToAll(msg); // 发送给所有的客户端}} catch (IOException e) {System.out.println("有人下线了: " + socket.getRemoteSocketAddress());Server.onLineSockets.remove(socket);e.printStackTrace();}}private void sendMsgToAll(String msg) throws IOExecption {// 发送给所有在线的 socket 管道接收for (Socket onLineSocket : Server.onLineSockets) {OUtputStream os = onLineSocket.getOutputStream();DataOutputStream dos = new DataOutputStream(os);dos.write(msg);dos.flush();}}
}

实现一个 BS 架构(浏览器+程序)

要求从浏览器中访问服务器, 并立即让服务器响应一个很简单的网页给浏览器展示, 网页内容就是“黑马程序员666”

image-20241005213841638

image-20241005213929070

public class ServerReaderThread extends Thread {private Socket socket;public SeverReaderThread(Socket socket) {this.socket = socket;}@Overridepublic void run() {// 立即响应一个网页内容:"黑马程序员"给浏览器展示try {OutputStream os = socket.getOutputStream();PrintStream ps = new PrintStream(os);ps.println("HTTP/1.1 200 OK");ps.println("Content-Type:text/html;charset=UTF-8");ps.println(); // 必须换行ps.println("<div style="color:red;font-size:120px;text-align:center" 黑马程序员磊哥</div>);} cathch (Exception e) {e.printStackTrace();}}
}

线程池优化 BS 架构

可以参考博主这篇JUC笔记
image-20241005214829542


public class Server {public static List<Socket> onLineSockets = new ArrayList<>();public static void main(String[] args) {System.out.println("--------服务器启动成功--------------");// 1. 创建ServerSocket的对象,同时为服务端注册端口ServerSocket serverSocket = new ServerSocket(8888);// 创建出一个线程池,负责处理通信管道的任务ThreadPoolExecutor pool = new ThreadPoolExecutor(16*2, 16*2, new ArrayBlockingQueue<>(8), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());while (true) {// 2. 使用serverSocket对象,调用一个 accept 方法,等待客户端连接请求Socket socket = serverSocket.accept();pool.execute(new ServerReaderRunnable(socket))}}
}
public class ServerReaderThread extends Runnable {private Socket socket;public SeverReaderThread(Socket socket) {this.socket = socket;}@Overridepublic void run() {// 立即响应一个网页内容:"黑马程序员"给浏览器展示try {OutputStream os = socket.getOutputStream();PrintStream ps = new PrintStream(os);ps.println("HTTP/1.1 200 OK");ps.println("Content-Type:text/html;charset=UTF-8");ps.println(); // 必须换行ps.println("<div style="color:red;font-size:120px;text-align:center" 黑马程序员磊哥</div>);}}
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于Zipf定律与TF—IDF的一个实践

在这篇文章中&#xff0c;我将通过机器学习中的线性回归来计算zipf定律中一个经验常数alpha&#xff0c;还会画TF-IDF的图像&#xff0c;此外还将简单介绍下与zipf、TF-IDF有关的知识。 在之前的一篇文章中我曾介绍过TF-IDF&#xff0c;但之后我又阅读了Ricardo Baeza-Yates和…

PELT算法

PELT算法的范畴 PELT算法&#xff08;Pruned Exact Linear Time&#xff09;属于时间序列分析和变点检测&#xff08;Change Point Detection&#xff09;范畴的算法。 从更广泛的角度来看&#xff0c;PELT算法还可以归类为以下几类算法的子集&#xff1a; 1. 时间序列分析&…

【数据结构】什么是红黑树(Red Black Tree)?

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 &#x1f4cc;红黑树的概念 &#x1f4cc;红黑树的操作 &#x1f38f;红黑树的插入操作 &#x1f38f;红黑树的删除操作 结语 &#x1f4cc;红黑树的概念 我们之前学过了…

codetop标签树刷题(四)!!暴打面试官!!!!

用于个人复习 1.二叉树的右视图2.二叉树最大宽度3.二叉树的最大深度4.N叉树的最大深度5.二叉树的最小深度6.子树的最大平均值7.求根节点到叶节点的数字之和8.另一棵树的子树9.对称二叉树 1.二叉树的右视图 给定一个二叉树的根节点root&#xff0c;想象自己站在它的右侧&#x…

TypeScript 封装 Axios 1.7.7

随着Axios版本的不同&#xff0c;类型也在改变&#xff0c;以后怎么写类型&#xff1f; yarn add axios1. 封装Axios 将Axios封装成一个类&#xff0c;同时重新封装request方法 重新封装request有几个好处&#xff1a; 所有的请求将从我们定义的requet请求中发送&#xff…

setTimeout,setInterval ,requestAnimationFrame定时器

setTimeout&#xff0c;setInterval &#xff0c;requestAnimationFrame定时器 定时器函数通常用于执行定时任务&#xff0c;也就是说你做了一个功能放在定时器函数里&#xff0c;它可以在特定的时间去执行你的指令&#xff0c;或者说隔多长时间&#xff08;单位时间内—毫秒为…

Centos Stream 9备份与恢复、实体小主机安装PVE系统、PVE安装Centos Stream 9

最近折腾小主机&#xff0c;搭建项目环境&#xff0c;记录相关步骤 数据无价&#xff0c;丢失难复 1. Centos Stream 9备份与恢复 1.1 系统备份 root权限用户执行进入根目录&#xff1a; cd /第一种方式备份命令&#xff1a; tar cvpzf backup.tgz / --exclude/proc --exclu…

计算机系统基础概述

什么是计算机&#xff1f; 计算机是一种利用电子技术进行信息处理的设备&#xff0c;它能够接收、存储、处理和提供数据。计算机通过执行一系列预定义的指令来处理数据&#xff0c;这些指令通常被称为程序。计算机的核心功能包括算术运算、逻辑判断、数据存储和信息检索 计算…

STM32 通用定时器

一、概述 STM32内部集成了多个定时/计数器&#xff0c;根据型号不同&#xff0c;STM32系列芯片最多包含8个定时/计数器。其中&#xff0c;TIM6、TIM7为基本定时器&#xff0c;TIM2~TIM5为通用定时器&#xff0c;TIM1、TIM8为高级控制定时器。 1.定时器的类型 基本定时器通用定…

微信小程序-npm支持-如何使用npm包

文章目录 1、在内建终端中打开2、npm init -y3、Vant Weapp4、通过 npm 安装5、构建 npm 1、在内建终端中打开 Windows PowerShell 版权所有 (C) Microsoft Corporation。保留所有权利。尝试新的跨平台 PowerShell https://aka.ms/pscore6PS C:\Users\dgq\WeChatProjects\minip…

python泵站设备运行预警信息管理系统

目录 功能介绍具体实现截图技术栈和环境说明python语言解决的思路性能/安全/负载方面核心代码部分展示详细视频演示源码获取方式 功能介绍 用户端 注册登录&#xff1a;用户可以注册账号并登录系统。 西电泵站简介&#xff1a;提供泵站的历史、功能和重要性等详细介绍。 泵站…

余承东直播论道智能驾驶:激光雷达不可或缺,华为ADS 3.0引领安全创新

华为余承东:激光雷达,智能驾驶安全性的关键 9月29日,华为消费者业务集团CEO余承东在一场引人注目的直播中,与知名主持人马东就智能驾驶技术的最新进展进行了深入交流。在这场直播中,余承东针对激光雷达在智能驾驶中的必要性问题,发表了明确且深刻的观点,引发了业界和公众…

在Docker中运行微服务注册中心Eureka

1、Docker简介&#xff1a; 作为开发者&#xff0c;经常遇到一个头大的问题&#xff1a;“在我机器上能运行”。而将SpringCloud微服务运行在Docker容器中&#xff0c;避免了因环境差异带来的兼容性问题&#xff0c;能够有效的解决此类问题。 通过Docker&#xff0c;开发者可…

角色动画——RootMotion全解

1. Unity(2022)的应用 由Animtor组件控制 在Animation Clip下可进行详细设置 ​ 官方文档的介绍(Animation选项卡 - Unity 手册) 上述动画类型在Rag选项卡中设置: Rig 选项卡上的设置定义了 Unity 如何将变形体映射到导入模型中的网格&#xff0c;以便能够将其动画化。 对于人…

Linux驱动开发——LED驱动开发

文章目录 1 概述1.1 说明 2 基础知识2.1 地址映射2.1.1 ioremap函数2.1.2 iounmap函数 2.2 I/O内存访问函数2.2.1 读操作函数2.2.2 写操作函数 3 硬件原理图分析4 RK3568 GPIO驱动原理4.1 引脚复用设置4.2 引脚驱动能力配置4.3 GPIO输入输出设置4.4 GPIO引脚高低电平设置 5 实验…

【GeekBand】C++设计模式笔记5_Observer_观察者模式

1. “组件协作”模式 现代软件专业分工之后的第一个结果是“框架与应用程序的划分”&#xff0c;“组件协作”模式通过晚期绑定&#xff0c;来实现框架与应用程序之间的松耦合&#xff0c;是二者之间协作时常用的模式。典型模式 Template MethodStrategyObserver / Event 2.…

HarmonyOS/OpenHarmony 自定义弹窗页面级层级控制解决方案

关键词&#xff1a;CuntomDialog自定义弹窗、SubWindow子窗口、页面级、弹窗层级控制、鸿蒙、弹窗展示层级异常 问题存在API版本&#xff1a;API10 - API12&#xff08;该问题已反馈&#xff0c;期望后续官方能增加页面级控制能力&#xff09; 在正常的鸿蒙app开发过程中&…

aws(学习笔记第二课) AWS SDK(node js)

aws(学习笔记第二课) 使用AWS SDK&#xff08;node js&#xff09; 学习内容&#xff1a; 使用AWS SDK&#xff08;node js&#xff09; 1. AWS SDK&#xff08;node js&#xff09; AWS支持多种SDK开发(除了AWS CLI&#xff0c;还支持其他的SDK) AndroidPythonNode.js(Javas…

约数个数约数之和

好久没发文章了.......不过粉丝还是一个没少...... 今天来看两道超级恶心的数论题目&#xff01; No.1 约数个数 No.2 约数之和 先来看第一道&#xff1a;约数个数 题目描述 给定 n 个正整数 ai​,请你输出这些数的乘积的约数个数,答案对 10^97 取模 输入格式 第一行包含…

五种IO模型与阻塞IO

一、前言 在网络中通信的本质其实是网络中的两台主机的进程间进行通信&#xff0c;而进程通信的本质就是IO。 IO分为输入&#xff08;input&#xff09;和输出&#xff08;output&#xff09;站在进程的角度讲&#xff0c;进程出去数据为输出&#xff0c;外部数据进入进程为输…