网络编程和反射
1.网络编程概述
- A:计算机网络
- 是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
- B:网络编程
- 就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。
2.网络编程三要素之IP
- 每个设备在网络中的唯一标识
- 每台网络终端在网络中都有一个独立的地址,我们在网络中传输数据就是使用这个地址。
- ipconfig:查看本机IP192.168.17.30
- ping:测试连接192.168.40.62
- 本地回路地址:127.0.0.1 255.255.255.255是广播地址
- IPv4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年初已经用尽。
- IPv6:8组,每组4个16进制数。
- 1a2b:0000:aaaa:0000:0000:0000:aabb:1f2f
- 1a2b::aaaa:0000:0000:0000:aabb:1f2f
- 1a2b:0000:aaaa::aabb:1f2f
- 1a2b:0000:aaaa::0000:aabb:1f2f
- 1a2b:0000:aaaa:0000::aabb:1f2f
3.网络编程三要素之端口号
- 每个程序在设备上的唯一标识
- 每个网络程序都需要绑定一个端口号,传输数据的时候除了确定发到哪台机器上,还要明确发到哪个程序。
- 端口号范围从0-65535
- 编写网络应用就需要绑定一个端口号,尽量使用1024以上的,1024以下的基本上都被系统程序占用了。
- 常用端口
- mysql: 3306
- oracle: 1521
- web: 80
- tomcat: 8080
- QQ: 4000
- feiQ: 2425
4.网络编程三要素协议
- 为计算机网络中进行数据交换而建立的规则、标准或约定的集合。
- UDP
- 面向无连接,数据不安全,速度快。不区分客户端与服务端。
- TCP
- 面向连接(三次握手),数据安全,速度略低。分为客户端和服务端。
- 三次握手: 客户端先向服务端发起请求, 服务端响应请求, 传输数据
5.UDP传输多线程
- 1.发送Send
- 创建DatagramSocket, 随机端口号
- 创建DatagramPacket, 指定数据, 长度, 地址, 端口
- 使用DatagramSocket发送DatagramPacket
- 关闭DatagramSocket
- 2.接收Receive
- 创建DatagramSocket, 指定端口号
- 创建DatagramPacket, 指定数组, 长度
- 使用DatagramSocket接收DatagramPacket
- 关闭DatagramSocket
- 从DatagramPacket中获取数据
- 3.接收方获取ip和端口号
- String ip = packet.getAddress().getHostAddress();
- int port = packet.getPort();
- A发送和接收在一个窗口完成
public class Demo3_MoreThread {
public static void main(String[] args) {
new Receive().start();
new Send().start();
}
}
class Receive extends Thread {
public void run() {
try {
DatagramSocket socket = new DatagramSocket(6666); //创建socket相当于创建码头
DatagramPacket packet = new DatagramPacket(new byte[1024], 1024); //创建packet相当于创建集装箱
while(true) {
socket.receive(packet); //接收货物
byte[] arr = packet.getData();
int len = packet.getLength();
String ip = packet.getAddress().getHostAddress();
System.out.println(ip + ":" + new String(arr,0,len));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Send extends Thread {
public void run() {
try {
DatagramSocket socket = new DatagramSocket(); //创建socket相当于创建码头
Scanner sc = new Scanner(System.in);
while(true) {
String str = sc.nextLine();
if("quit".equals(str))
break;
DatagramPacket packet = //创建packet相当于创建集装箱
new DatagramPacket(str.getBytes(), str.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666);
socket.send(packet); //发货
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
6.TCP通信
在Java中,提供了两个类用于实现TCP通信程序:
- 客户端:
java.net.Socket
类表示。创建Socket
对象,向服务端发出连接请求,服务端响应请求,两者建立连接开始通信。 - 服务端:
java.net.ServerSocket
类表示。创建ServerSocket
对象,相当于开启一个服务,并等待客户端的连接。
Socket类
Socket client = new Socket("127.0.0.1", 6666);
成员方法:
public InputStream getInputStream()
: 返回此套接字的输入流。public OutputStream getOutputStream()
: 返回此套接字的输出流。public void close()
:关闭此套接字。public void shutdownOutput()
: 禁用此套接字的输出流。
ServerSocket类
ServerSocket server = new ServerSocket(6666);
成员方法
public Socket accept()
:侦听并接受连接,返回一个新的Socket对象,用于和客户端实现通信。该方法会一直阻塞直到建立连接。
简单的TCP网络程序
-
【服务端】启动,创建ServerSocket对象,等待连接。
-
【客户端】启动,创建Socket对象,请求连接。
-
【服务端】接收连接,调用accept方法,并返回一个Socket对象。
-
【客户端】Socket对象,获取OutputStream,向服务端写出数据。
-
【服务端】Scoket对象,获取InputStream,读取客户端发送的数据。
-
【服务端】启动,创建ServerSocket对象,等待连接。
-
【客户端】启动,创建Socket对象,请求连接。
-
【服务端】接收连接,调用accept方法,并返回一个Socket对象。
-
【客户端】Socket对象,获取OutputStream,向服务端写出数据。
-
【服务端】Scoket对象,获取InputStream,读取客户端发送的数据。
服务器代码:
public static void main(String[] args) throws IOException {
//创建服务器
ServerSocket server = new ServerSocket(8888);
//获取请求的socket
Socket socket = server.accept();
//创建输入流
InputStream is = socket.getInputStream();
//读read
byte[] bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
//获取输出
OutputStream os = socket.getOutputStream();
//给客户端打印数据
os.write("收到谢谢!".getBytes());
//释放资源
socket.close();
server.close();
}
客户端代码:
public static void main(String[] args) throws IOException {
//设置端口号
Socket socket = new Socket("127.0.0.1",8888);
//创建输出流
OutputStream os = socket.getOutputStream();
//给服务器发送数据
os.write("你好服务器".getBytes());
//获取输入流
InputStream is = socket.getInputStream();
//读取服务器返回
byte[] bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
//释放资源
socket.close();
}
7.文件上传
- 【客户端】输入流,从硬盘读取文件数据到程序中。
- 【客户端】输出流,写出文件数据到服务端。
- 【服务端】输入流,读取文件数据到服务端程序。
- 【服务端】输出流,写出文件数据到服务器硬盘中。
- 【服务端】获取输出流,回写数据。
- 【客户端】获取输入流,解析回写数据。
客户端:1输入流、2输出流、6输入流
服务器:3输入流、4输出流、5输出流
服务器代码:
public static void main(String[] args) throws IOException {
//创建服务器对象
ServerSocket server = new ServerSocket(8888);
while (true) {
//获取对象
Socket socket = server.accept();
new Thread(new Runnable() {
@Override
public void run() {
try {
//输入流
InputStream is = socket.getInputStream();
//判断文件夹是否存在
File file = new File("D:\\bbb");
if (!file.exists()) {
file.mkdir();
}
//随机名
String str = "\\cxl" + System.currentTimeMillis() + Math.random() * 100 + ".jpg";
//绑定目的地
FileOutputStream fos = new FileOutputStream(file + str);
//输入
int len;
byte[] bytes = new byte[1024];
while ((len = is.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
//输出
socket.getOutputStream().write("上传成功!".getBytes());
fos.close();
socket.close();
} catch (IOException e) {
System.out.println(e);
}
}
}).start();
}
//释放
//fos.close();
//server.close();
//socket.close();
}
客户端代码:
public static void main(String[] args) throws IOException {
//创建输入流
FileInputStream fis = new FileInputStream("D:\\a.jpg");
//创建socket对象
Socket socket = new Socket("127.0.0.1", 8888);
//输出流
OutputStream os = socket.getOutputStream();
byte[] bytes = new byte[1024];
int len;
while ((len = fis.read(bytes)) != -1) {
os.write(bytes, 0, len);
}
//关闭输出流
socket.shutdownOutput();
//输入流
InputStream is = socket.getInputStream();
while ((len = is.read(bytes)) != -1) {
System.out.println(new String(bytes, 0, len));
}
//释放流
socket.close();
}