Java基础----网络编程基础 笔记
1、网络基础
-
网络通讯
- 概念:两台设备之间通过网络实现数据传输
- 网络通信:将数据通过网络从一台设备传输到另一台设备
java.nat
包下提供了一系列的类或接口,供程序员使用,完成网络通信
-
网络
- 概念:两台或多台设备通过一定物理设备连接起来构成了网络
- 根据网络的覆盖范围不同,对网络进行分类:
局域网:覆盖范围最小,仅仅覆盖一个教室或者一个机房
城域网:覆盖范围较大,可以覆盖一个城市
广域网:覆盖范围最大,可以覆盖全国,甚至全球,万维网时广域网的代表
-
ip地址
- 概念:用于唯一事变网络中的每一台计算机
- 查看ip地址的表示形式:点分十进制:xx.xx.xx.xx
- 每一个十进制数的范围0~255
- 查看IP地址:ipconfig
- IP地址的组成=网络地址+主机地址
- ipv6是互联网工程任务组设计的用于替代iPv4的下一代ip协议,其地址数量号称可以为全世界的每一粒沙子编上一个地址
- 由于ipv4最大的问题在于网络地址资源有限,严重制约了互联网的应用和发展。Ipv6的使用,不仅能解决网络地址资源数量的问题,而且也解决了多种接入设备连入互联网的障碍
- ipv4地址的分类
-
域名
- 概念:将ip地址映射成域名,例如www.baidu.com
- 好处:方便记忆
-
端口号
- 概念:用于表示计算机上某一个特定的网络程序
- 表示形式:以整数形式,范围:0~65535
- 0~1024已经被占用:比如ssh是22,ftp是21,smtp是25,http是80
- 常见的网络程序端口号:
- tomcat:8080
- mysql:3306
- oracle:1521
- sqlserver:1433
-
网络通信协议
数据的组织形式,例如tcp/ip协议
-
传输层的TCP和UDP协议
- TCP协议:传输控制协议
- 使用TCP协议前,须先建立TCP连接,形成传输数据通道
- 传输前采用”三次握手“方式,是可靠的
- TCP协议进行通信的两个应用程序:客户端、服务端
- 在连接中可进行大数据量的传输
- 传输完毕,需释放已建立的连接,效率低
2.UDP协议
1. 将数据、源、目的封装成数据包,不需要建立连接
2. 每个数据报的大小限制在64k内
3. 因无需连接,故是不可靠的
4. 发送数据结束时无需释放资源(因为不是面向连接的),速度快 - TCP协议:传输控制协议
2、InetAddress
- 相关方法
- getLocalHost:获取本机InetAddress对象
- getByName:根据指定主机名/域名获取ip地址对象
- getHostName:获取InetAddress对象的主机名
- getHostAddress:获取InetAddress对象的地址
import java.net.InetAddress;
import java.net.UnknownHostException;
//演示InetAddress类的使用
public class API_ {
public static void main(String[] args) throws UnknownHostException {
//1.获取本机的InetAddress对象
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost);
//2.根据指定主机名/域名获取ip地址对象
InetAddress byName = InetAddress.getByName("LAPTOP-7KBLS3C4");
System.out.println(byName);
InetAddress byName1 = InetAddress.getByName("www.baidu.com");
System.out.println(byName1);
//3.通过InetAddress对象获取对应的地址
System.out.println(byName1.getHostAddress());
//4.通过InetAddress对象,获取对应的主机名域名
System.out.println(byName1.getHostName());
}
}
3、Socket
- 基本介绍:
- 套接字(Socket)开发网络应用程序被广泛采用,以至于称为事实上的标准
- 通信的两端都要有套接字,是两台机器间通信的端点
- 网络通信其实就是套接字(Socket)间通信
- Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输
- 一般主动发起通信的应用程序属于客户端,等待通信请求的为服务端
- 基于客户端-服务器端的网络通信
- 底层使用的是TCP/IP协议
- 基于socket的TCP编程和UDP编程
- 当我们需要通信时(读写数据):
socket.getOutputStream()
socket.getInputStream()
4、TCP编程
-
基本步骤:
服务器端:
(1)监听端口ServerSocket serverSocket = new ServerSocket(9999);
(2)创建套接字对象Socket accept = serverSocket.accept();
(3)生成输入字节流InputStream inputStream = socket.getInputStream()
(4)IO读取
(5)关闭流对象和套接字对象客户端:
(1)连接服务器端(ip,端口)Socket socket = new Socket("127.0.0.1", 9999);
(2)生成输出字节流OutputStream outputStream = socket.getOutputStream();
(3)写入outputStream.write("hello server".getBytes());
(4)设置一个结束标记socket.shutdownOutput();
(5)关闭流对象和套接字对象 -
基于socket的TCP编程示例(字节流):
服务器端:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketTCP01Server {
public static void main(String[] args) throws IOException {
//当没有客户端连接9999端口时,程序会阻塞,等待连接
//如果客户端连接,则会返回Socket对象,程序继续
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端在9999端口监听,等待连接。。。");
Socket accept = serverSocket.accept();
System.out.println("服务端socket="+accept.getClass());
//通过socket.getInputStream()读取客户端写入到数据通道的数据,显示
InputStream inputStream = accept.getInputStream();
//IO读取
byte[] buf = new byte[1024];
int readLen = 0;
while ((readLen = inputStream.read(buf))!=-1){
System.out.println(new String(buf,0,readLen));
}
OutputStream outputStream = accept.getOutputStream();
//通过输出流,写入数据到数据通道
outputStream.write("hello client".getBytes());
accept.shutdownOutput();
//关闭输入流和Socket
inputStream.close();
outputStream.close();
accept.close();
serverSocket.close();
}
}
客户端:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class SocketTCP01Client {
public static void main(String[] args) throws IOException {
//连接服务器端(ip,端口)
Socket socket = new Socket("127.0.0.1", 9999);
System.out.println("客户端socket返回="+socket.getClass());
//连接上后,生成socket,通过socket.getOutputStream()得到和socket对象关联的输出流对象
OutputStream outputStream = socket.getOutputStream();
//通过输出流,写入数据到数据通道
outputStream.write("hello server".getBytes());
//设置一个结束标记
socket.shutdownOutput();
InputStream inputStream = socket.getInputStream();
//IO读取
byte[] buf = new byte[1024];
int readLen = 0;
while ((readLen = inputStream.read(buf))!=-1){
System.out.println(new String(buf,0,readLen));
}
//关闭流对象和socket,必须关闭
outputStream.close();
inputStream.close();
socket.close();
}
}
- 基于socket的TCP编程示例(字符流):
StreamUtils类:
import java.io.*;
public class StreamUtils {
//将输入流转换成byte[],即可以把文件的内容读入到byte[]
public static byte[] streamToByteArray(InputStream is) throws IOException {
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.close();
return array;
}
public static String streamToString(InputStream is) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
StringBuffer stringBuffer = new StringBuffer();
String line;
while ((line=bufferedReader.readLine())!=null){//当读到null就结束了
stringBuffer.append((line+"\r\n"));
}
return bufferedReader.toString();
}
}
服务器端:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketTCP01Server {
public static void main(String[] args) throws IOException {
//当没有客户端连接9999端口时,程序会阻塞,等待连接
//如果客户端连接,则会返回Socket对象,程序继续
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端在9999端口监听,等待连接。。。");
Socket accept = serverSocket.accept();
System.out.println("服务端socket="+accept.getClass());
//通过socket.getInputStream()读取客户端写入到数据通道的数据,显示
InputStream inputStream = accept.getInputStream();
//IO读取
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
System.out.println(s);
OutputStream outputStream = accept.getOutputStream();
//通过输出流,写入数据到数据通道
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("hello client字符流");
bufferedWriter.newLine();
bufferedWriter.flush();
//关闭输入流和Socket
bufferedReader.close();
bufferedWriter.close();
accept.close();
serverSocket.close();
}
}
客户端:
import java.io.*;
import java.net.Socket;
public class SocketTCP01Client {
public static void main(String[] args) throws IOException {
//连接服务器端(ip,端口)
Socket socket = new Socket("127.0.0.1", 9999);
System.out.println("客户端socket返回="+socket.getClass());
//连接上后,生成socket,通过socket.getOutputStream()得到和socket对象关联的输出流对象
OutputStream outputStream = socket.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
//通过输出流,写入数据到数据通道
bufferedWriter.write("hello server字符流");
//设置一个结束标记
bufferedWriter.newLine();
bufferedWriter.flush();
InputStream inputStream = socket.getInputStream();
//IO读取
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
System.out.println(s);
//关闭流对象和socket,必须关闭
bufferedReader.close();
bufferedWriter.close();
socket.close();
}
}
- 示例3
服务器端:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
//服务器端
public class TCPFileUploadServer {
public static void main(String[] args) throws IOException {
//1.服务端在本机监听8888
ServerSocket serverSocket = new ServerSocket(8888);
//2.等待连接
System.out.println("服务器在8888端口监听。。。");
Socket accept = serverSocket.accept();
//3.读取客户端发送的数据
//通过Socket得到输入流
BufferedInputStream bufferedInputStream = new BufferedInputStream(accept.getInputStream());
byte[] bytes = StreamUtils.streamToByteArray(bufferedInputStream);
//4.将得到bytes数组写入到指定的路径
String destFilePath = "D:\\qieeeee.jpg";
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(destFilePath));
bufferedOutputStream.write(bytes);
bufferedOutputStream.close();
//向客户端回复“收到图片”
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
bufferedWriter.write("收到图片");
bufferedWriter.flush();//把内容刷新到数据通道
//设置一个结束标记
accept.shutdownOutput();
bufferedWriter.close();
bufferedInputStream.close();
accept.close();
serverSocket.close();
}
}
客户端:
import java.io.*;
import java.net.Socket;
//客户端
public class TCPFileUploadClient {
public static void main(String[] args) throws IOException {
//客户端连接服务器,得到Socket对象
Socket socket = new Socket("127.0.0.1", 8888);
System.out.println("连接服务器成功。。。。。");
//创建读取磁盘文件的输入流(输入图片数据到程序)
String filePath = "D:\\壁纸1.jpg";
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
//bytes是filePath对应的字节数组
byte[] bytes = StreamUtils.streamToByteArray(bis);
//通过socket获取到输出流,将bytes数据发送给服务器
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());
//将文件对应的字节数组的内容写入到数据通道
bufferedOutputStream.write(bytes);
bis.close();
socket.shutdownOutput();
//收到”收到图片“
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s=bufferedReader.readLine();
System.out.println(s);
bufferedReader.close();
/*InputStream inputStream = socket.getInputStream();
String s = StreamUtils.streamToString(inputStream);
System.out.println(s);*/
inputStream.close();
bufferedOutputStream.close();
socket.close();
}
}
5、UDP编程(了解)
-
基本介绍:
- 类
DatagramSocket
和DatagramPacket
实现了基于UDP协议网络程序 - UDP数据报通过数据报套接字DatagramSocket发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达
- DatagramSocket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号
- UDP协议中每个数据报都给出了完整的地址信息,因此无需建立发送方和接收方的连接
- 没有明确的服务端和客户端,演变为数据的发送端和接收端
- 接收数据和发送数据是通过
DatagramSocket
对象来完成 - 将数据封装到
DatagramPacket
对象(装包) - 当接收到
DatagramPacket
对象需要进行拆包,取出数据 DatagramSocket
可以指定在哪个端口接收数据
- 类
-
基本流程
- 核心的两个类/对象
DatagramSocket
和DatagramPacket
- 建立发送端,接收端
- 建立数据
- 调用
DatagramSocket
的发送、接收方法 - 关闭
DatagramSocket
- 核心的两个类/对象
-
示例:
Udp_A.java:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
//先是接收端,再是发送端
public class Udp_A {
public static void main(String[] args) throws IOException {
//1.创建一个DatagramSocket对象,准备在9999接收或发送数据
DatagramSocket datagramSocket = new DatagramSocket(9999);
//2. 构建一个DatagramSocket对象,准备接收数据
//在前面讲解UDP协议的时候,说过每个数据包大小在64k以内
byte[] buf = new byte[64*1024];
DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length);
//3. 准备 调用 接收方法(包好的数据包,需要拆包)
//并且填充到datagramPacket
//当有数据包发送到本机的9999端口时,就会接收到数据,没有数据包发送就会阻塞等待
System.out.println("等待接收数据。。。。。");
datagramSocket.receive(datagramPacket);
//4. 可以把datagramPacket进行拆包,取出数据并且显示
int len = datagramPacket.getLength();//实际接收的数据字节长度
byte[] data = datagramPacket.getData();//接收的数据
String s = new String(data,0,len);
System.out.println(s);
//=================================回复B的,发送
//将需要发送的数据 封装到datagramPacket对象
data = "收到了B的发送,我(A)也要发送了".getBytes();
//封装的datagramPacket对象,data内容字节数组、其数组长度、主机IP、端口号
DatagramPacket datagramPacket1 =
new DatagramPacket(data, data.length, InetAddress.getByName("192.168.199.1"),9998);
//发送
datagramSocket.send(datagramPacket1);
//==============================================
//5. 关闭资源
datagramSocket.close();
}
}
Udp_B.java:
import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;
//先是发送端,再是接收端
public class Udp_B {
public static void main(String[] args) throws IOException {
//1.创建一个DatagramSocket对象,准备在9998发送数据
DatagramSocket datagramSocket = new DatagramSocket(9998);
//2. 将需要发送的数据 封装到datagramPacket对象
byte[] data = "哈哈哈UDP,我(B)要发送了".getBytes();
//封装的datagramPacket对象,data内容字节数组、其数组长度、主机IP、端口号
DatagramPacket datagramPacket =
new DatagramPacket(data, data.length, InetAddress.getByName("192.168.199.1"),9999);
//3. 发送
datagramSocket.send(datagramPacket);
//===================接收A的数据===============================================
//构建一个DatagramSocket对象,准备接收数据
byte[] buf = new byte[64*1024];
datagramPacket = new DatagramPacket(buf, buf.length);
//准备 调用 接收方法(包好的数据包,需要拆包)
datagramSocket.receive(datagramPacket);
//可以把datagramPacket进行拆包,取出数据并且显示
int len = datagramPacket.getLength();//实际接收的数据字节长度
data = datagramPacket.getData();//接收的数据
String s = new String(data,0,len);
System.out.println(s);
//===================接收A的数据=================================================
//4. 关闭资源
datagramSocket.close();
}
}