JavaSE学习总结第26天_网络编程

时间:2023-12-28 10:45:08

 

26.01  网络编程概述

网络编程:就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。

26.02  网络模型概述和图解

计算机网络之间以何种规则进行通信,就是网络模型研究问题。

网络模型一般是指

OSI(Open System Interconnection开放系统互连)参考模型

TCP/IP参考模型

JavaSE学习总结第26天_网络编程

OSI参考模型七层简述:

1.物理层:主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后在转化为1、0,也就是我们常说的数模转换与模数转换)。这一层的数据叫做比特。 

2.数据链路层:主要将从物理层接收的数据进行MAC地址(网卡的地址)的封装与解封装。常把这一层的数据叫做帧。在这一层工作的设备是交换机,数据通过交换机来传输。 

3.网络层:主要将从下层接收到的数据进行IP地址(例192.168.0.1)的封装与解封装。在这一层工作的设备是路由器,常把这一层的数据叫做数据包。 

4.传输层:定义了一些传输数据的协议和端口号(WWW端口80等),如:TCP(传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据),UDP(用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如QQ聊天数据就是通过这种方式传输的)。 主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组。常常把这一层数据叫做段。 

5.会话层:通过传输层(端口号:传输端口与接收端口)建立数据传输的通路。主要在你的系统之间发起会话或者接受会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名) 

6.表示层:主要是进行对接收的数据进行解释、加密与解密、压缩与解压缩等(也就是把计算机能够识别的东西转换成人能够能识别的东西(如图片、声音等)。 

7.应用层:主要是一些终端的应用,比如说FTP(各种文件下载),WEB(IE浏览),QQ之类的(可以把它理解成我们在电脑屏幕上可以看到的东西.就是终端应用)。

26.03  网络编程三要素概述

网络通信三要素

1.IP地址: InetAddress网络中设备的标识,不易记忆,可用主机名

2.端口号: 用于标识进程的逻辑地址,不同进程的标识

3.传输协议: 通讯的规则常见协议:TCP,UDP

26.04  网络编程三要素之IP概述1

IP地址:InetAddress

1.网络中设备的标识

2.不易记忆,可用主机名

3.本地回环地址:127.0.0.1  主机名:localhost

 

IP地址的组成

IP地址 = 网络号码+主机地址

A类IP地址:第一段号码为网络号码,剩下的三段号码为本地计算机的号码

B类IP地址:前二段号码为网络号码,剩下的二段号码为本地计算机的号码

C类IP地址:前三段号码为网络号码,剩下的一段号码为本地计算机的号码

 

A类 1.0.0.1---127.255.255.254

(1)10.X.X.X是私有地址(私有地址就是在互联网上不使用,而被用在局域网络中的地址)

(2)127.X.X.X是保留地址,用做循环测试用的。

B类 128.0.0.1---191.255.255.254

172.16.0.0---172.31.255.255是私有地址。169.254.X.X是保留地址。

C类 192.0.0.1---223.255.255.254

192.168.X.X是私有地址

D类 224.0.0.1---239.255.255.254 

E类 240.0.0.1---247.255.255.254

 

DOS命令 ipconfig:查看本机IP地址

xxx.xxx.xxx.0 网络地址

xxx.xxx.xxx.255 广播地址

127.0.0.1 回环地址,可用于测试本机的网络是否有问题. ping 127.0.0.1 

26.05  InetAddress类的概述和使用

为了方便我们对IP地址的获取和操作,java提供了一个类InetAddress 供我们使用

InetAddress:此类表示互联网协议 (IP) 地址。IP 地址是 IP 使用的 32 位或 128 位无符号数字,它是一种低级协议,UDP 和 TCP 协议都是在它的基础上构建的。

方法:

1.public static InetAddress[] getAllByName(String host)throws UnknownHostException

在给定主机名的情况下,根据系统上配置的名称服务返回其 IP 地址所组成的数组。

2.public String getHostName()

获取此 IP 地址的主机名。

3.public String getHostAddress()

返回 IP 地址字符串(以文本表现形式)。

例:

 InetAddress address = InetAddress.getByName("192.168.1.88");
// 获取此 IP 地址的主机名
String name = address.getHostName();
// 返回 IP 地址字符串(以文本表现形式)。
String ip = address.getHostAddress();
System.out.println("主机名:"+name);
System.out.println("IP:"+ip);

26.06  网络编程三要素之端口

物理端口 网卡口

逻辑端口

1:每个网络程序都会至少有一个逻辑端口

2:用于标识进程的逻辑地址,不同进程的标识

3:有效端口:0~65535,其中0~1024系统使用或保留端口

26.07  网络编程三要素之协议

协议:通讯的规则,常见协议:TCP,UDP

UDP:

1.将数据源和目的封装成数据包中,不需要建立连接

2.每个数据报的大小在限制在64k

3.因无连接,是不可靠协议

4.不需要建立连接,速度快

TCP:

1.建立连接,形成传输数据的通道

2.在连接中进行大数据量传输

3.通过三次握手完成连接,是可靠协议

4.必须建立连接,效率会稍低

26.08  Socket通信原理

Socket套接字:网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字

Socket原理机制:

1.通信的两端都有Socket

2.网络通信其实就是Socket间的通信

3.数据在两个Socket间通过IO传输

26.09  UDP协议发送数据

DatagramSocket:此类表示用来发送和接收数据报包的套接字。数据报套接字是包投递服务的发送或接收点。

DatagramPacket:此类表示数据报包。数据报包用来实现无连接包投递服务。

发送端步骤:

1:建立udp的socket服务

2:将要发送的数据封装成数据包

3:通过udp的socket服务,将数据包发送出

4:关闭资源

例:

 public class Send
{
public static void main(String[] args) throws IOException
{
// 创建发送端Socket对象
DatagramSocket ds = new DatagramSocket(); // 创建数据
byte[] bys = "hello,udp,我来了".getBytes();
// 长度
int length = bys.length;
// IP地址对象
InetAddress address = InetAddress.getByName("192.168.12.92");
// 端口
int port = 10086; //将数据打包,包含内容、长度、IP地址、端口号
DatagramPacket dp = new DatagramPacket(bys, length, address, port); // 发送数据包
ds.send(dp); // 释放资源
ds.close();
}
}

26.10  UDP协议接收数据

接收端步骤:

1:建立udp的socket服务.

2:通过receive方法接收数据

3:将收到的数据存储到数据包对象中

4:通过数据包对象的功能来完成对接收到数据进行解析

5:可以对资源进行关闭

例:

 public class Receive
{
public static void main(String[] args) throws IOException
{
// 创建接收端Socket对象
DatagramSocket ds = new DatagramSocket(10000); // 创建一个数据包(接收容器)
byte[] bys = new byte[1024];
int length = bys.length;
DatagramPacket dp = new DatagramPacket(bys, length); // 调用Socket对象的接收方法接收数据
ds.receive(dp); // 阻塞式 // 解析数据包
// 获取对方的ip
InetAddress address = dp.getAddress();
String ip = address.getHostAddress();
// 获取数据缓冲区
byte[] bys2 = dp.getData();
// 获取数据的实际长度
int len = dp.getLength();
String s = new String(bys2, 0, len);
System.out.println("ip:"+ip);
System.out.println("传递的数据:"+ s);
// 释放资源
ds.close();
}
}

26.11  UDP协议发送和接收数据代码优化

例:

 public class Send
{
public static void main(String[] args) throws IOException
{
// 创建发送端的Socket对象
DatagramSocket ds = new DatagramSocket(); // 创建数据并打包
byte[] bys = "helloworld".getBytes();
DatagramPacket dp = new DatagramPacket(bys, bys.length,
InetAddress.getByName("192.168.1.99"), 10001); // 发送数据
ds.send(dp); // 释放资源
ds.close();
}
} --------------------------------------------------------------
public class Receive
{
public static void main(String[] args) throws IOException
{
// 创建接收端的Socket对象
DatagramSocket ds = new DatagramSocket(10001); // 创建一个包裹
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length); // 接收数据
ds.receive(dp); // 解析数据
String ip = dp.getAddress().getHostAddress();
String s = new String(dp.getData(), 0, dp.getLength());
System.out.println("ip:" + ip);
System.out.println("数据:" + s); // 释放资源
ds.close();
}
}

26.12  发送端的数据来自于键盘录入案例

从键盘录入数据进行发送,如果输入的是886那么客户端就结束输入数据。

 public class Send
{
public static void main(String[] args) throws IOException
{
// 创建发送端的Socket对象
DatagramSocket ds = new DatagramSocket(); // 封装键盘录入数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while ((line = br.readLine()) != null)
{
if ("886".equals(line))
{
break;
} // 创建数据并打包
byte[] bys = line.getBytes();
DatagramPacket dp = new DatagramPacket(bys, bys.length,
InetAddress.getByName("192.168.1.99"), 10001);
//192.168.1.255为广播地址 // 发送数据
ds.send(dp);
} // 释放资源
ds.close();
}
}
--------------------------------------------------------------
public class Receive
{
public static void main(String[] args) throws IOException
{
// 创建接收端的Socket对象
DatagramSocket ds = new DatagramSocket(10001); while (true)
{
// 创建一个包裹
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length); // 接收数据
ds.receive(dp); // 解析数据
String ip = dp.getAddress().getHostAddress();
String s = new String(dp.getData(), 0, dp.getLength());
System.out.println("from " + ip + " data is : " + s);
} // 释放资源
// 接收端应该一直开着等待接收数据,是不需要关闭
// ds.close();
}
}

26.13  多线程实现聊天室程序

 public class Practice
{
public static void main(String[] args) throws IOException
{
DatagramSocket dsSend = new DatagramSocket();
DatagramSocket dsReceive = new DatagramSocket(10001); Send st = new Send(dsSend);
Receive rt = new Receive(dsReceive); Thread t1 = new Thread(st);
Thread t2 = new Thread(rt); t1.start();
t2.start();
}
}
--------------------------------------------------------------
发送端:
public class Send implements Runnable
{
private DatagramSocket ds; public Send(DatagramSocket ds)
{
this.ds = ds;
} @Override
public void run()
{
try
{
// 封装键盘录入数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while ((line = br.readLine()) != null)
{
if ("886".equals(line))
{
break;
} // 创建数据并打包
byte[] bys = line.getBytes();
DatagramPacket dp = new DatagramPacket(bys, bys.length,InetAddress.getByName("192.168.1.255"), 10001); // 发送数据
ds.send(dp);
} // 释放资源
ds.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
--------------------------------------------------------------
接收端:
public class Receive implements Runnable
{
private DatagramSocket ds; public Receive(DatagramSocket ds)
{
this.ds = ds;
} @Override
public void run()
{
try
{
while (true)
{
// 创建一个包裹
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length); // 接收数据
ds.receive(dp); // 解析数据
String ip = dp.getAddress().getHostAddress();
String s = new String(dp.getData(), 0, dp.getLength());
System.out.println("来自" + ip + "的数据: " + s);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}

26.14  TCP协议发送数据

TCP协议发送数据:

A:创建发送端的Socket对象,这一步如果成功,就说明连接已经建立成功了

B:获取输出流,写数据

C:释放资源

 

TCP协议一定要先开服务器。否则报错:java.net.ConnectException: Connection refused: connect

 

public Socket(String host,int port) throws UnknownHostException,IOException

创建一个流套接字并将其连接到指定主机上的指定端口号。

 

例:

 public class Client
{
public static void main(String[] args) throws IOException
{
// 创建发送端的Socket对象
// Socket(InetAddress address, int port)
// Socket(String host, int port)
// Socket s = new Socket(InetAddress.getByName("192.168.1.88"), 10002);
Socket s = new Socket("192.168.1.88", 10002); // 获取输出流,写数据
// public OutputStream getOutputStream()
OutputStream os = s.getOutputStream();
os.write("hello,tcp".getBytes()); // 释放资源
s.close();
}
}

26.15  TCP协议接收数据

TCP协议接收数据:

A:创建接收端的Socket对象

B:监听客户端连接。返回一个对应的Socket对象

C:获取输入流,读取数据显示在控制台

D:释放资源

 

例:

 public class Server
{
public static void main(String[] args) throws IOException
{
// 创建接收端的Socket对象
// ServerSocket(int port)
ServerSocket ss = new ServerSocket(10002); // 监听客户端连接。返回一个对应的Socket对象
// public Socket accept()
Socket s = ss.accept(); // 侦听并接受到此套接字的连接。此方法在连接传入之前一直阻塞。 // 获取输入流,读取数据显示在控制台
InputStream is = s.getInputStream(); byte[] bys = new byte[1024];
int len = is.read(bys); // 阻塞式方法
String str = new String(bys, 0, len); String ip = s.getInetAddress().getHostAddress(); System.out.println(ip + "---" + str); // 释放资源
s.close();
// ss.close(); //这个不应该关闭
}
}

26.16  服务器给客户端一个反馈案例

 //服务端
public class Server
{
public static void main(String[] args) throws IOException
{
// 创建服务器Socket对象
ServerSocket ss = new ServerSocket(10002); // 监听客户端的连接
Socket s = ss.accept(); // 阻塞 // 获取输入流
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys); // 阻塞
String server = new String(bys, 0, len);
System.out.println("server:" + server); // 获取输出流
OutputStream os = s.getOutputStream();
os.write("数据已经收到".getBytes()); // 释放资源
s.close();
// ss.close();
}
}
--------------------------------------------------------------
//客户端
public class Client
{
public static void main(String[] args) throws IOException
{
// 创建客户端Socket对象
Socket s = new Socket("192.168.1.88", 10002); // 获取输出流
OutputStream os = s.getOutputStream();
os.write("hello".getBytes()); // 获取输入流
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);// 阻塞
String client = new String(bys, 0, len);
System.out.println("client:" + client); // 释放资源
s.close();
}
}

26.17  客户端键盘录入服务器控制台输出

 //服务端
public class Server
{
public static void main(String[] args) throws IOException
{
// 创建服务器Socket对象
ServerSocket ss = new ServerSocket(10003); // 监听客户端连接
Socket s = ss.accept(); // 包装通道内容的流
BufferedReader br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
String line = null;
while ((line = br.readLine()) != null)
{
System.out.println(line);
} // br.close();
s.close();
// ss.close();
}
}
--------------------------------------------------------------
//客户端
public class Client
{
public static void main(String[] args) throws IOException
{
// 创建客户端Socket对象
Socket s = new Socket("192.168.1.88", 10003); // 键盘录入数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 把通道内的流给包装一下
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream())); String line = null;
while ((line = br.readLine()) != null)
{
// 键盘录入数据要自定义结束标记
if ("886".equals(line))
{
break;
}
bw.write(line);
bw.newLine();
bw.flush();
} // 释放资源
// bw.close();
// br.close();
s.close();
}
}

26.18  TCP上传文本文件并给出反馈

 //服务端
public class Server
{
public static void main(String[] args) throws IOException
{
// 创建服务器端的Socket对象
ServerSocket ss = new ServerSocket(10003); // 监听客户端连接
Socket s = ss.accept();// 阻塞 // 封装通道内的流
BufferedReader br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
// 封装文本文件
BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java")); String line = null;
while ((line = br.readLine()) != null)
{
// 阻塞
// if("over".equals(line)){
// break;
// }
bw.write(line);
bw.newLine();
bw.flush();
} // 给出反馈
BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
bwServer.write("文件上传成功");
bwServer.newLine();
bwServer.flush(); // 释放资源
bw.close();
s.close();
}
}
--------------------------------------------------------------
//客户端
public class Client
{
public static void main(String[] args) throws IOException
{
// 创建客户端Socket对象
Socket s = new Socket("192.168.1.99", 10003); // 封装文本文件
BufferedReader br = new BufferedReader(new FileReader(
"InetAddressDemo.java"));
// 封装通道内流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream())); String line = null;
while ((line = br.readLine()) != null)
{ // 阻塞
bw.write(line);
bw.newLine();
bw.flush();
} //自定义一个结束标记
// bw.write("over");
// bw.newLine();
// bw.flush(); //Socket提供了一个终止,它会通知服务器没有数据过来了
s.shutdownOutput(); // 接收反馈
BufferedReader brClient = new BufferedReader(new InputStreamReader(
s.getInputStream()));
String client = brClient.readLine(); // 阻塞
System.out.println(client); // 释放资源
br.close();
s.close();
}
}

26.19  TCP协议上传图片并给出反馈

 //服务端
public class Server
{
public static void main(String[] args) throws IOException
{
// 创建服务器Socket对象
ServerSocket ss = new ServerSocket(10004); // 监听客户端连接
Socket s = ss.accept(); // 封装通道内流
BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
// 封装图片文件
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("D:\\bj.jpg")); byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1)
{
bos.write(bys, 0, len);
bos.flush();
} // 给一个反馈
OutputStream os = s.getOutputStream();
os.write("图片上传成功".getBytes()); bos.close();
s.close();
}
}
--------------------------------------------------------------
//客户端
public class Client
{
public static void main(String[] args) throws IOException
{
// 创建客户端Socket对象
Socket s = new Socket("192.168.1.88", 10004); // 封装图片文件
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
"D:\\001.jpg"));
// 封装通道内的流
BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream()); byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1)
{
bos.write(bys, 0, len);
bos.flush();
} s.shutdownOutput(); // 读取反馈
InputStream is = s.getInputStream();
byte[] bys2 = new byte[1024];
int len2 = is.read(bys2);
String client = new String(bys2, 0, len2);
System.out.println(client); // 释放资源
bis.close();
s.close();
}
}

26.20  多线程改进多个客户端上传文件案例

 //用户线程
public class UserThread implements Runnable
{
private Socket s; public UserThread(Socket s)
{
this.s = s;
} @Override
public void run()
{
try
{
// 封装通道内的流
BufferedReader br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
// 封装文本文件
// BufferedWriter bw = new BufferedWriter(new
// FileWriter("Copy.java")); // 为了防止名称冲突
String newName = System.currentTimeMillis() + ".java";
BufferedWriter bw = new BufferedWriter(new FileWriter(newName)); String line = null;
while ((line = br.readLine()) != null)
{ // 阻塞
bw.write(line);
bw.newLine();
bw.flush();
} // 给出反馈
BufferedWriter bwServer = new BufferedWriter(
new OutputStreamWriter(s.getOutputStream()));
bwServer.write("文件上传成功");
bwServer.newLine();
bwServer.flush(); // 释放资源
bw.close();
s.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
--------------------------------------------------------------
//服务端
public class Server
{
public static void main(String[] args) throws IOException
{
// 创建服务器Socket对象
ServerSocket ss = new ServerSocket(10005); while (true)
{
Socket s = ss.accept();
new Thread(new UserThread(s)).start();
}
}
}
--------------------------------------------------------------
//客户端
public class Client
{
public static void main(String[] args) throws IOException
{
// 创建客户端Socket对象
Socket s = new Socket("192.168.1.99", 10005); // 封装文本文件
// BufferedReader br = new BufferedReader(new FileReader(
// "InetAddressDemo.java"));
BufferedReader br = new BufferedReader(new FileReader(
"ReceiveDemo.java"));
// 封装通道内流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream())); String line = null;
while ((line = br.readLine()) != null)
{ // 阻塞
bw.write(line);
bw.newLine();
bw.flush();
} // Socket提供了一个终止,它会通知服务器你别等了,我没有数据过来了
s.shutdownOutput(); // 接收反馈
BufferedReader brClient = new BufferedReader(new InputStreamReader(
s.getInputStream()));
String client = brClient.readLine(); // 阻塞
System.out.println(client); // 释放资源
br.close();
s.close();
}
}