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 = serv服务器托管网erSocket.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 = "srcqie1.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+"rn");
}
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端退出");
}
}
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
相关推荐: django+flask+python高校教材管理系统47nia
本.4论文结构 绪论:剖析项目可行性,表明研究方向。 开发技术:系统关键运用了Python技术性、Django框架、B/S架构和myspl数据库查询,并进行了详细介绍[6]。 系统分析:包含系统的总体构造,用例图和结构图。 系统设计:软件程序功能模块和数据库查…