行业知识
JAVA-网络编程基础
2026-11-14 06:50:34
来源:互联网转载
JAVA-网络编程
01. 网络通信
- 概念:两台设备之间通过网络实现数据传输
- 网络通信:将数据通过网络从一台设备传输给另一台设备
- java.net包下���供了一系列类或接口,供程序员使用,完成网络通信
02. 网络
- 概念:两台设备或多台设备通过一定的物理设备连接起来构成了网络
- 根据网络的覆盖范围不同,对网络进行分类
- 区域网:覆盖范围最小,仅仅覆盖一个教室或一个机房
- 城域网:覆盖范围较大,可以覆盖一个城市
- 广域网:覆盖范围最大,可以覆盖全国,甚至是全球,万维网是广域网的代表
03. ip地址
1. 基本介绍
- 概念:用于唯一的标识网络中的每台计算机/主机
- 查看ip地址:ipconfig
- ip地址的表现形式:点分十进制 xx.xx.xx.xx
- ip表示:4个字节(32位)表示, 一个字节的范围是0 ~ 255
- 每个十进制的范围:0 ~ 255
- ip地址的组成 = 网络地址 + 主机地址,比如:192.168.11.35
- IPv6是互联网工程任务组设计的用于代替IPv4的下一代IP写一,其地址数量号称可以为全世界的每一粒沙子编上一个地址
- ipv6使用128位表示地址, 是ipv4的四倍
- 由于IPv4最大的问题在于网络的地址资源有限,严重制约了互联网的应用和发展. IPv6的使用不仅能解决网络地址资源数量的问题,而且也解决了多种接入设备连入互联网的障碍
2. ipv4地址分类
04. 域名
1. 介绍
- www.baidu.com
- 好处:为了方便记忆,解决记ip的困难
- 概念:将ip地址映射成域名,如何映射,http协议
2. 端口号
- 概念: 用于标识计算机上某个特定的网络程序
- 表示形式:以整数形式,端口范围0 ~ 65535[2个字节表示端口0 ~ 2^16 - 1]
- 0 ~ 1024已经被占用,比如 ssh 22,ftp 21, smtp 25,http 80
- 常见的网络程序端口
- tomcat:8080
- mysql:3306
- oracle:1521
- sqlserver:1433
05. 网络通信协议
1. 网络协议的理解
网络协议是一种规则和约定的集合,用于在计算机网络中进行通信和数据交换。这些规则规定了数据在网络中的传输方式、格式、错误检测和纠正方法等。网络协议使得不同类型的计算机和设备可以互相通信,实现数据的可靠传输和有效交换。
想象一下,网络协议就像人们在进行交流时遵循的语言和礼仪规范。它确保了交流的顺畅和准确,使得信息能够按照一定的格式和流程进行传递。常见的网络协议包括TCP/IP、HTTP、FTP、SMTP等,它们各自负责不同的网络通信任务,如数据传输、网页浏览、文件下载、电子邮件发送等。
2. 协议(TCP/IP)
- TCP/IP (Transmission ControlProtocol/Internet Protocol)的简写,中文译名为传输控制协议/因特网互联协议,又叫网络通讯协议,这个协议是Internet最基本的协议、Internet国际互联网络的基础,简单地说,就是由网络层的IP协议和传输层的TCP协议组成的。[示意图]
- 示意图
3. 模型
06. TCP和UDP
1. TCP协议:传输控制协议
- 使用TCP协议前,须先建立TCP连接,形成传输数据通道
- 传输前,采用"三次握手"方式,是可靠的
- TCP协议进行通信的两个应用进程:客户端、服务端
- 在连接中可进行大数据量的传输
- 传输完毕,需释放已建立的连接,效率低
2. UDP协议:用户数据协议
- 将数据、源、目的封装成数据包,不需要建立连接
- 每个数据报的大小限制在64K内,不适合传输大量数据
- 因无需连接,故是不可靠的
- 发送数据结束时无需释放资源(因为不是面向连接的),速度快
07. InetAddress类
1. 相关方法
- 获取本机InetAddress对象getLocalHost
- 根据指定主机名/域名获取ip地址对象getByName
- 获取InetAddress对象的主机名getHostName
- 获取InetAddress对象的地址getHostAddress
2. 应用案例
要求:编写代码, 获取计算机的主机名和IP地址的相关API
import java.net.InetAddress;import java.net.UnknownHostException;/** * 演示InetAddress类 */public class API_ { public static void main(String[] args) throws UnknownHostException { //1. 获取本机的InetAddress对象 InetAddress inetAddress = InetAddress.getLocalHost(); System.out.println(inetAddress);//1.1 显示计算机名+ip //2. 根据指定主机名 获取InetAddress对象 InetAddress host1 = InetAddress.getByName("kratolt"); System.out.println("host1= " + host1); //3. 根据域名返回 InetAddress对象, 比如www.baidu.com 对应的 InetAddress host2 = InetAddress.getByName("www.baidu.com"); System.out.println(host2); //4. 通过 InetAddress 对象,获取对应的地址 String hostAddress = host2.getHostAddress(); System.out.println("host2对应的ip= " + hostAddress); //5. 通过InetAddress 对象,获取对应的主机名、或者域名 String hostName = host2.getHostName(); System.out.println("host2对应的主机名/域名" + hostName); }} 08. Socket
1. 基本介绍
- 套接字(Socket)开发网络应用程序被广泛采用,以至于成为事实上的标准。
- 通信的两端都要有Socket,是两台机器间通信的端点
- 网络通信其实就是Socket之间的通信
- Socket允许程序把网络连接当成一个流,数据在两个Socket之间通过IO传输
- 一般主动发起通信的应用程序属客户端,等待通讯请求的为服务端
2. 示意图
当我们需要通讯的时候(读写数据)
- socket.getOutputStream()
- socket.getInputStream()
Socket 的理解
- TCP编程,可靠
- UDP编程,不可靠
- 客户端和服务器在通常情况下,是在不同主机的。碍于本人,客户端和服务器端在一台主机
09. TCP网络通信编程
1. 基本介绍
- 给予客户端—服务端的网络通信
- 底层使用的是TCP/IP协议
- 基于Socket的TCP编程
2. 应用案例1(使用字节流)
- 编写一个服务器端和一个客户端
- 服务器端在9999端口监听
- 客户端连接到服务器端,发送“hello,server!”,然后退出
- 服务器端接收到 客户端发的信息,输出,退出
服务端类:
import java.io.IOException;import java.io.InputStream;import java.net.ServerSocket;import java.net.Socket;/** * 服务端 */public class SocketTCP01Server { public static void main(String[] args) throws IOException { //思路: //1. 在本机的9999端口监听,等待连接 //1.1 细节:要求在本机没有其他服务在监听9999 //1.2 细节:这个ServerSocket 可以通过accept() 返回多个Socket[多个客户端连接服务器的并发] ServerSocket serverSocket = new ServerSocket(9999); System.out.println("服务端,在9999端口监听,等待连接.."); //2. 当有客户端连接9999端口时,程序会阻塞,等待连接 //2.1 如果有客户端连接,则会返回Socket对象,程序继续运行 Socket socket = serverSocket.accept(); System.out.println("服务器端socket = " + socket.getClass()); //3. 通过socket。getInputStream() 读取客户端写入数据到数据通道的数据,显示 InputStream inputStream = socket.getInputStream(); //4. IO读取 byte[] bytes = new byte[1024]; int readLean = 0; while ((readLean = inputStream.read(bytes)) != -1) { System.out.println(new String(bytes, 0, readLean));//根据读取到的实际长度,显示内容 } //5. 关闭流对象和socket inputStream.close(); socket.close(); serverSocket.close();//关闭 }} 客户端类:
package com.yzjedu.socket_;import java.io.IOException;import java.io.OutputStream;import java.net.InetAddress;import java.net.Socket;/** * 03. 客户端 */public class SocketTCP01Client { public static void main(String[] args) throws IOException { //思路 //1. 连接服务端(ip,端口) //1.1 解读连接本机的9999端口,如果连接成功,返回Socket对象 Socket socket = new Socket(InetAddress.getLocalHost(), 9999); System.out.println("客户端socket = " + socket.getClass()); //2. 连接上后,生成Socket,通过socket.getOutputStream() // 得到和socket 对象关联的输出流对象 OutputStream outputStream = socket.getOutputStream(); //3. 通过输出流,写入数据到 数据通道 outputStream.write("hello, server!".getBytes()); //4. 关闭流对象和socket,必须关闭 outputStream.close(); socket.close(); }} 3. 应用案例2(使用字节流)
- 编写- -个服务端,和一个客户端
- 服务器端在9999端口监听
- 客户端连接到服务端,发送"hello, server"并接收服务器端回发的"hello,client",再退出
- 服务器端接收到客户端发送的信息,输出,并发送"hello, client", 再退出
- 注意:在发送完之后要设置结束标记
- 设置写入结束标记socket.shutdownOutput()
服务器端类:
import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;/** * 04. 服务端 */@SuppressWarnings("all")public class SocketTCP02Server { public static void main(String[] args) throws IOException { //思路: //1. 在本机的9999端口监听,等待连接 //1.1 细节:要求在本机没有其他服务在监听9999 //1.2 细节:这个ServerSocket 可以通过accept() 返回多个Socket[多个客户端连接服务器的并发] ServerSocket serverSocket = new ServerSocket(9999); System.out.println("服务端,在9999端口监听,等待连接.."); //2. 当有客户端连接9999端口时,程序会阻塞,等待连接 //2.1 如果有客户端连接,则会返回Socket对象,程序继续运行 Socket socket = serverSocket.accept(); System.out.println("服务器端socket = " + socket.getClass()); //3. 通过socket。getInputStream() 读取客户端写入数据到数据通道的数据,显示 InputStream inputStream = socket.getInputStream(); //4. IO读取 byte[] bytes = new byte[1024]; int readLean = 0; while ((readLean = inputStream.read(bytes)) != -1) { System.out.println(new String(bytes, 0, readLean));//根据读取到的实际长度,显示内容 } //5. 获取socket县关联的输出流 OutputStream outputStream = socket.getOutputStream(); outputStream.write("hello, client".getBytes()); socket.shutdownOutput(); //6. 关闭流对象和socket outputStream.close(); inputStream.close(); socket.close(); serverSocket.close();//关闭 }} 客户端类:
import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.InetAddress;import java.net.Socket;/** * 05. 客户端 */@SuppressWarnings("all")public class SocketTCP02Client { public static void main(String[] args) throws IOException { //思路 //1. 连接服务端(ip,端口) //1.1 解读连接本机的9999端口,如果连接成功,返回Socket对象 Socket socket = new Socket(InetAddress.getLocalHost(), 9999); System.out.println("客户端socket = " + socket.getClass()); //2. 连接上后,生成Socket,通过socket.getOutputStream() // 得到和socket 对象关联的输出流对象 OutputStream outputStream = socket.getOutputStream(); //3. 通过输出流,写入数据到 数据通道 outputStream.write("hello, server!".getBytes()); //3.1 设置结束标记 socket.shutdownOutput(); //4. 获取socket关联的输入流,读取数据(字节),并显示 InputStream inputStream = socket.getInputStream(); byte[] bytes = new byte[1024]; int readLen = 0; while ((readLen = inputStream.read(bytes)) != -1) { System.out.println(new String(bytes, 0, readLen)); } //5. 关闭流对象和socket,必须关闭 inputStream.close(); outputStream.close(); socket.close(); }} 4. 应用案例3(使用字符流)
- 编写-个服务端,和一个客户端
- 服务端在9999端口监听
- 客户端连接到服务端,发送"hello, server" ,并接收服务端回发的"hello,client",再退出
- 服务端接收到客户端发送的信息,输出,并发送"hello, client",再退出
- 注意编写结束标记
- shutdownOutput()
- write.newLIne()//换行符,注意需要使用readLine()
服务器端:
import java.io.*;import java.net.ServerSocket;import java.net.Socket;@SuppressWarnings("all")public class SocketTCP03Server { public static void main(String[] args) throws IOException { //思路: //1. 在本机的9999端口监听,等待连接 //1.1 细节:要求在本机没有其他服务在监听9999 //1.2 细节:这个ServerSocket 可以通过accept() 返回多个Socket[多个客户端连接服务器的并发] ServerSocket serverSocket = new ServerSocket(9999); System.out.println("服务端,在9999端口监听,等待连接.."); //2. 当有客户端连接9999端口时,程序会阻塞,等待连接 //2.1 如果有客户端连接,则会返回Socket对象,程序继续运行 Socket socket = serverSocket.accept(); System.out.println("服务器端socket = " + socket.getClass()); //3. 通过socket。getInputStream() 读取客户端写入数据到数据通道的数据,显示 InputStream inputStream = socket.getInputStream(); //4. IO读取,使用字符流,使用InputStreamReader 将 inputStream 转换成字符流 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String s = bufferedReader.readLine(); System.out.println(s);//输出 //5. 获取socket相关联的输出流 OutputStream outputStream = socket.getOutputStream(); BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream)); bufferedWriter.write("hello, Client 字符流"); bufferedWriter.newLine(); bufferedWriter.flush(); //6. 关闭流对象和socket bufferedWriter.close(); bufferedReader.close(); inputStream.close(); socket.close(); serverSocket.close();//关闭 }} 客户端:
import java.io.*;import java.net.InetAddress;import java.net.Socket;@SuppressWarnings("all")public class SocketTCP03Client { public static void main(String[] args) throws IOException { //思路 //1. 连接服务端(ip,端口) //1.1 解读连接本机的9999端口,如果连接成功,返回Socket对象 Socket socket = new Socket(InetAddress.getLocalHost(), 9999); System.out.println("客户端socket = " + socket.getClass()); //2. 连接上后,生成Socket,通过socket.getOutputStream() // 得到和socket 对象关联的输出流对象 OutputStream outputStream = socket.getOutputStream(); //3. 通过输出流,写入数据到 数据通道,使用字符流 BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream)); bufferedWriter.write("hello,server 字符流"); //3.1 设置结束标记 bufferedWriter.newLine();//插入一个换行符,表示写入内容结束,注意:要求对方使用readLine() bufferedWriter.flush();//使用字符流,需要手动刷新,否则不会写入数据通道 //4. 获取socket关联的输入流,读取数据(字节),并显示 InputStream inputStream = socket.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String s = bufferedReader.readLine(); System.out.println(s); //5. 关闭流对象和socket,必须关闭 bufferedReader.close(); bufferedWriter.close(); outputStream.close(); socket.close(); }} 5. 应用案例4
- 编写一个服务端,和一个客户端
- 服务器端在8888端口监听
- 客户端连接到服务端,发送一-张图片d:\lqie.png
- 服务器端接收到客户端发送的图片,保存到Src下,发送"收到图片"再退出
- 客户端接收到服务端发送的"收到图片",再退出
- 该程序要求使用StreamUtils.java,我们直接使用(在开发里你会经常使用到同事或者公司的开发工具类)
服务器端:
import java.io.*;import java.net.ServerSocket;import java.net.Socket;public class TCPFileUploadServer { public static void main(String[] args) throws Exception { //1. 服务端在本机,监听8888 ServerSocket serverSocket = new ServerSocket(8888); System.out.println("服务端在8888端口监听..."); //2. 等待客户端的连接 Socket socket = serverSocket.accept(); //3. 读取客户端发送的数据 //3.1 通过socket得到一个输入流 BufferedInputStream bis = new BufferedInputStream(socket.getInputStream()); byte[] bytes = StreamUtils.streamToByteArray(bis); //4. 将得到bytes数组,写入到指定的路径,就得到一个文件 String filePath = "src\qie1.png"; BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath)); bos.write(bytes); bos.close(); //5. 向客户端回复收到图片 //通过socket 获取到输出流 BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); writer.write("服务器:收到图片"); writer.flush(); socket.shutdownOutput();//设置写入结束标记 //6. 关闭其他流 writer.close(); bis.close(); socket.close(); serverSocket.close(); }} 客户端:
import java.io.*;import java.net.InetAddress;import java.net.Socket;public class TCPFileUploadClient { public static void main(String[] args) throws Exception { //1. 创建客户端 Socket socket = new Socket(InetAddress.getLocalHost(), 8888); //2. 创建读取磁盘的输入流 String filePath = "d:\qie.png"; BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath)); //2.1bytes 就是 filePath对应的字节数组 byte[] bytes = StreamUtils.streamToByteArray(bis); //3. 通过socket获取输出流,将bytes数据发送给服务端 BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream()); bos.write(bytes);//将文件对应的字节数组的内容,写入到数据通道 bos.flush(); bis.close(); socket.shutdownOutput();//设置写入数据的结束标记 //接受从服务器回复的消息 InputStream inputStream = socket.getInputStream(); //使用StreamUtils 的方法,直接将 inputStream 读取到的内容 转成字符串 String s = StreamUtils.streamToString(inputStream); System.out.println(s); //4. 关闭相关的流 inputStream.close(); bos.close(); socket.close(); }} StreamUtils.java:
import java.io.BufferedReader;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;/** * 此类用于演示关于流的读写方法 * */public class StreamUtils {/** * 功能:将输入流转换成byte[], 即可以把文件的内容读入到byte[] * @param is * @return * @throws Exception */public static byte[] streamToByteArray(InputStream is) throws Exception{ByteArrayOutputStream bos = new ByteArrayOutputStream();//创建输出流对象byte[] b = new byte[1024];//字节数组int len;while((len=is.read(b))!=-1){//循环读取bos.write(b, 0, len);//把读取到的数据,写入bos}byte[] array = bos.toByteArray();//然后将bos 转成字节数组bos.close();return array;}/** * 功能:将InputStream转换成String * @param is * @return * @throws Exception */public static String streamToString(InputStream is) throws Exception{BufferedReader reader = new BufferedReader(new InputStreamReader(is));StringBuilder builder= new StringBuilder();String line;while((line=reader.readLine())!=null){builder.append(line+"\r\n");}return builder.toString();}} 6. netstat指令
- netstat -an可以查看当前主机网络情况,包括端口监听情况和网络连接情况
- netstat -an | more可以分页显示
- 要求在dos控制台下执行win+r
说明:
- Listening表示某个端口在监听
- 如果有一个外部程序(客户端)连接到该端口,就会显示一条连接信息.
- 可以输入ctrl + C退出指令
- 当客户端连接到服务端后,实际上客户端也是通过一个端口和服务端进行通讯的,这个端口是TCP/IP来分配的,是不确定的,是随机的.
- 程序验证+ netstat
10. UDP 网络通信编程[了解]
1. 基本介绍
- 类DatagramSocket和DatagramPacket[数据包/数据报]实现了基于UDP协议网络程序。
- UDP数据报通过数据报套接字DatagramSocket发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。
- DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号
- UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接
UDP说明:
- 没有明确的服务端和客户端,演变成数据的发送端和接收端
- 接收数据和发送数据是通过DatagramSocket对象完成
- 将数据封装到DatagramPacket 对象/装包
- 当接收到DatagramPacket 对象,需要进行拆包,取出数据
- DatagramSocket 可以指定在那个端口接收数据
2. 基本流程
- 核心的两个类/对象DatagramSocket与DatagramPacket
- 建立发送端,接收端(没有服务端和客户端概念)
- 发送数据前,建立数据包/报DatagramPacket对象
- 调用DatagramSocket的发送、接收方法
- 关闭DatagramSocket
3. 应用案例
- 编写一个接收端A,和一一个发送端B
- 接收端A在9999端口等待接收数据(接收receive、发送send)
- 发送端B向接收端A发送数据"hello ,明天吃火锅~”
- 接收端A接收到发送端B发送的数据,回复"好的,明天见",再退出
- 发送端接收回复的数据,再退出
接收端A:
import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.SocketException;public class UDPReceiverA { public static void main(String[] args) throws IOException { //1. 创建一个DatagramSocket 对象,准备在9999接收数据 DatagramSocket socket = new DatagramSocket(9999); //2. 构建一个DatagramPacket 对象,准备接收数据 //2.1 一个数据包最大是 64k byte[] buf = new byte[1024]; DatagramPacket packet = new DatagramPacket(buf, buf.length); //3. 调用接收方法,将通过网络传输的 DatagramPacket 对象 //填充到packet对象 //注意:当有数据包发送到 本机的9999端口,就会接收到数据 //如果没有数据包发送到,本机的9999端口,就会堵塞等待 System.out.println("接收端A 等待接收数据..."); socket.receive(packet); //4. 可以把packet进行一个拆包,取出数据,并显示 int length = packet.getLength();//实际接收到的数据长度 byte[] data = packet.getData();//接收到数据 String s = new String(data, 0, length); System.out.println(s); //--------回复信息---------- //将需要发送的数据,封装到DatagramPacket对象 data = "A:好的,没有问题".getBytes(); //说明: 封装的 DatagramPacket对象 (内容字节数组, data.length, 主机ip, d端口) DatagramPacket datagramPacket = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.131.1"), 9998); socket.send(datagramPacket); //5. 关闭资源 socket.close(); System.out.println("A端退出"); }} 发送端B:
import java.io.IOException;import java.net.*;public class UDPSenderB { public static void main(String[] args) throws IOException { //1. 创建 DatagramSocket对象,准备在 9998接收数据 DatagramSocket datagramSocket = new DatagramSocket(9998); //2. 将需要发送的数据,封装到DatagramPacket对象 byte[] data = "B:hello,明天吃火锅".getBytes(); //3. 说明: 封装的 DatagramPacket对象 (内容字节数组, data.length, 主机ip, d端口) DatagramPacket datagramPacket = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.131.1"), 9999); datagramSocket.send(datagramPacket); //---------接受从A端回复的信息----------- byte[] bytes = new byte[1024]; DatagramPacket datagramPacket1 = new DatagramPacket(bytes, bytes.length); datagramSocket.receive(datagramPacket1); int length = datagramPacket1.getLength(); byte[] data1 = datagramPacket1.getData(); String s = new String(data1, 0, length); System.out.println(s); //4. 关闭资源 datagramSocket.close(); System.out.println("B端退出"); }}
下一篇:美国服务器国内哪里跳板?