网络编程
三要素:1.IP地址 2.端口 3.协议
InetAddress互联网协议 (IP) 地址
封装了IP地址的类
用法:
public static void main(String[] args){
//获取IP地址
try {
InetAddress ia=InetAddress.getByName("www.baidu.com");
System.out.println(ia);//www.baidu.com/110.242.68.3
//返回本地域名
System.out.println(ia.getHostName());//www.baidu.com
//返回IP地址
System.out.println(ia.getHostAddress());//110.242.68.3
System.out.println(ia.getCanonicalHostName());//110.242.68.4
//获取本机地址
InetAddress localHost = ia.getLocalHost();
System.out.println(localHost);
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
URL路径
用法:
public static void main(String[] args) {
//URL路径
try {
URL url=new URL("https://www.baidu.com:80/index.html#muzhou");
System.out.println("协议:"+url.getProtocol());//协议:https
System.out.println("域名:"+url.getHost());//域名:www.baidu.com
System.out.println("端口:"+url.getPort());//端口:80
System.out.println("资源:"+url.getFile());//资源:/index.html
System.out.println("锚点:"+url.getRef());//锚点:muzhou
System.out.println("相对路径:"+url.getPath());//相对路径:/index.html
System.out.println("参数:"+url.getQuery());//null
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
常用端口:
3306 mysql
1521 oracle
80 web
8080 tomcat
4000 QQ
2425 飞秋feiQ
协议:
UDP协议:
用户数据 面向无连接 数据不安全 速度快 不区分客户端和服务端
(例子:相当于发短信 不论对方是否在线 是否能接收到)
Socket通信(套接字):
网络上具有唯一标识的IP地址和端口号组合在一起 才能构成唯一能识别的标识符套接字
通信的两端都有Socket
网络通信其实就是Socket间的通信
数据在Socket中通过IO流传输
案例:UDP传输多线程
//(服务端)接收
public class Reciver extends Thread {
public void run(){
//建立码头
DatagramSocket s=null;
try {
//指定端口号9999
s=new DatagramSocket(9999);
//货轮
byte[] b=new byte[1024];
//集装箱接受数据
DatagramPacket p=new DatagramPacket(b,1024);
while(true){
//将数据装载到集装箱中
s.receive(p);
//获取数据来源的地址
InetAddress ip=p.getAddress();
String msg=new String(b);
System.out.println("从"+ip+"发送过来"+msg);
}
} catch (Exception e) {
throw new RuntimeException(e);
}finally{
s.close();
}
}
}
//(客户端)发送
public class Sender extends Thread {
public void run(){
//创建码头
DatagramSocket s=null;
while(true){
try {
s=new DatagramSocket();
//准备备货物
Scanner sc=new Scanner(System.in);
System.out.println("请客户端输入:");
String msg=sc.next();
//创建货轮
byte[] b=msg.getBytes();
//获取客户地址
InetAddress ip=InetAddress.getByName("127.0.0.1");
//将货物装入集装箱
DatagramPacket p=new DatagramPacket(b,0,b.length,ip,9999);
//发送
s.send(p);
} catch (Exception e) {
throw new RuntimeException(e);
}finally{
s.close();
}
}
}
}
//测试
public static void main(String[] args) {
Reciver r=new Reciver();
r.start();
Sender s=new Sender();
s.start();
}
(重点)TCP协议:
传输控制 面向连接(三次握手) 数据安全 速度略慢 分为客户端和服务段
(例子1:打电话 呼叫 接听 数据传输)(例子2:网站访问:客户端发送请求 连接服务器 数据传输)
案例:TCP传输多线程
public class Sender extends Thread{
public void run(){
ServerSocket ss=null;
BufferedReader br=null;
try {
//创建服务端的套接字
ss=new ServerSocket(8888);
//阻塞
Socket socket=ss.accept();
//读取客户端的流
InputStream in=socket.getInputStream();
br=new BufferedReader(new InputStreamReader(in));
while(true){
String msg=br.readLine();
System.out.println("客户端发来:"+msg);
}
} catch (Exception e) {
throw new RuntimeException(e);
}finally{
if(br!=null){
try {
br.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
public class Client extends Thread {
OutputStream out=null;
BufferedWriter bw=null;
public void run(){
try {
//定位
Socket s=new Socket("127.0.0.1",8888);
//发送
out=s.getOutputStream();
bw=new BufferedWriter(new OutputStreamWriter(out));
Scanner sc=new Scanner(System.in);
while(true){
System.out.println("请客户端输入:");
String str=sc.next();
bw.write(str);
bw.newLine();
bw.flush();
}
} catch (IOException e) {
throw new RuntimeException(e);
}finally{
if(bw!=null){
try {
bw.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
public class Test_Client {
public static void main(String[] args) {
Client c=new Client();
c.start();
}
}
public class Test_Sender {
public static void main(String[] args) {
Sender s=new Sender();
s.start();
}
}
反射 (解剖 类)
对于任意一个类 都能知道这个类中的所有属性和方法
对于任意一个对象 都能够调用它任意的方法和属性
动态获取的信息以及动态调用对象的方法 称为java的反射机制
类的加载:
类的加载概述:当程序要使用某个类时,如果该类没有加载到内存中 系统将通过加载,连接,初始化三步实现对这个类进行初始化
加载:将class文件读入内存 并为之创建一个class对象 任何类被使用时系统都会创建一个class对象
连接:
验证:是否有正确的内部结构 并和其他类协调一致
准备:负责为类的静态成员分配内存 并赋值 默认值
解析:将类的二进制数据中的符号引用替换为直接引用
初始化
平时使用的
类加载器(classLoader):负责将.class文件加载到内存中 并为之生成对应的class对象
类加载器分为:根类加载器 扩展类加载器 系统类加载器
字节码加载时机:
创建类的实例(new)
访问类的静态变量或者为静态变量赋值
调用类的静态方法 使用反射方式强制创建某个类或接口对应的class对象
初始化某个类的子类 直接使用java.exe命令运行某个主类
获取字节码文件
三种方式获取字节码文件
//三种方式获取字节码文件
//第一种
Class c1=Class.forName("com.muzhou.lesson.Person");
//第二种
Class c2=Person.class;
//第三种
Person p=new Person();
Class c3=p.getClass();
//验证三种方法取出的字节码文件是否相同
System.out.println(c1==c2);//true
System.out.println(c2==c3);//true
反射创建无参构造和有参构造
第一种
//获取反射无参构造和有参构造创建
public static void main(String[] args) throws Exception {
//Class类的.newInstance()是使用该类的无参构造方法创建对象
//如果一个类没有无参构造 就不能这么创建 会报错 InstantiationException
Class clazz=Class.forName("com.muzhou.lesson.clazz.Person");
//通过无参构造创建对象
/* Person p =(Person) clazz.newInstance();
System.out.println(p);//Person{name='null', age=0}*/
//获取有参构造 没有无参构造创建对象
//clazz.getConstructor(String.class,int.class);//String.class,int.class要与Person类中的属性对应
Constructor c = clazz.getConstructor(String.class, int.class);
//通过有参构造创建对象
Person p=(Person)c.newInstance("张三",23);
System.out.println(p);//Person{name='张三', age=23}
第二种
//反射其实就是在分解class对象
Class<Person> clazz=Person.class;
//这个过期了 Person p1 =clazz.newInstance();
//现在使用.getDeclaredConstructor().newInstance();创建一个无参构造器对象 再用对象创建实例
Person p1 = clazz.getDeclaredConstructor().newInstance();
p1.setName("张三");
p1.setAge(23);
System.out.println(p1);
Constructor<Person> c = clazz.getDeclaredConstructor(String.class, int.class);
Person p2 =c.newInstance("李四", 24);
p2.eat();
p2.eat(10);
System.out.println(p2);
反射获取成员变量(如果是私有的就用暴力反射)
Class clazz=Class.forName("com.muzhou.lesson.clazz.Person");
Constructor c = clazz.getConstructor(String.class, int.class);
Person p =(Person)c.newInstance("张三", 23);
//clazz.getFields("name");可以获取到类中指定的字段(必须是可见的public)
/* Field f = clazz.getFields("name");
f.set(p,"李四");*/
//暴力反射
Field f = clazz.getDeclaredField("name");
//在这一步去除私有权限 变成public
f.setAccessible(true);
f.set(p,"李四");
System.out.println(p);
反射获取方法
//反射获取方法
Class clazz=Class.forName("com.muzhou.lesson.clazz.Person");
Constructor c = clazz.getConstructor(String.class, int.class);
Person p =(Person) c.newInstance("张三", 23);
//通过clazz获取Method 返回的是Method 获取eat方法
Method m1 = clazz.getMethod("eat");//eat不用加()
m1.invoke(p);
//获取带参数的方法
Method m2 = clazz.getMethod("eat", int.class);
m2.invoke(p,10);
反射获取所有属性
Class<Person> clazz=Person.class;
//获取所有成员变量
Field[] fields =clazz.getDeclaredFields();
System.out.println(fields.length);//2
for (Field f : fields) {
System.out.println(f.getName()+"----"+f.getAnnotatedType());
}
//获取所有构造
Constructor<?>[] c = clazz.getDeclaredConstructors();
for (Constructor cs : c) {
System.out.println(cs);
}
//获取所有方法
Method[] m = clazz.getDeclaredMethods();
for (Method method : m) {
System.out.println( method.getName()+"返回类型"+method.getGenericReturnType()+"方法中形式参数"+
method.getGenericParameterTypes());
}