Java第二十二天~第二十三天、12.9~12.10

day22

一、网络编程:

1、网络编程的三要素是什么?
1)找到IP地址
2)必须有端口
3)必须有协议(TCP协议,UDP协议)
2、IP地址:
PC机器都有唯一的标识:ip
ip地址:192.168.1.100 已经优化的ip
ip每一个段落转成二进制:
11000000 10101000 00000001 01100100
192 168 1 100
常见的IP:
A类:1.0.0.1—127.255.255.254:第一个号段为网络号段,后三个号段为主机号段
256^3=16777216台计算机 (强大的部门),通常:国防部(美国的五角大楼)
B类:128.0.0.1—191.255.255.254:前两个号段为网络号段,后两个号段为主机号段()
256^2: 通常大学里面或者一些地方政府部门
C类:192.0.0.1—223.255.255.254:前三个好号段为网络号段,后一个号段为主机号段
192.168.1.100(私人地址:家庭或者单位)
D类 224.0.0.1—239.255.255.254
E类 240.0.0.1—247.255.255.254
回环地址(也可表示本机地址):127.0.0.1
3、协议:
TCP协议和UDP协议 区别:
TCP协议:(客户端和服务器端的交互)
1)建立连接通道(通道内的流:(使用的是最基本的字节流))
2)可靠协议
3)由于可靠协议,并且需要建立连接通道(服务器端需要等待客户端连接),执行效率低
4)使用TCP协议(TCP编程)可以发送大量的数据,文件大小无限制
UDP协议:(发送端和接收端)
1)无需建立连接通道(数据报包的形式发送数据的)
2)不可靠协议
3)由于不可靠,无需建立连接通道,所以它的执行效率高
4)UDP协议(UDP编程)发送数据有限制

4、获取IP地址

package org.westos_01_IP地址;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * InetAddress类没有构造方法 此类表示互联网协议 (IP) 地址。
 *   public static InetAddress getByName(String host)throws UnknownHostException
 *     在给定主机名的情况下确定主机的 IP 地址
 *   //public String getHostName()获取此 IP 地址的主机名。 
 *   //public String getHostAddress()返回 IP 地址字符串(以文本表现形式)。
 * @author 小鑫
 */
public class InetAddressDemo {

    public static void main(String[] args) throws UnknownHostException {

        // public static InetAddress getByName(String host)throws
        // UnknownHostException在给定主机名的情况下确定主机的 IP 地址
        // 该主机名可以是计算机名(PC机器的计算机名称),也可以是ip地址的文本表现形式,通过这个方法返回的是ip地址对象
        //InetAddress ip = InetAddress.getByName("172.20.10.6");
        //System.out.println(ip);//  /172.20.10.6
        InetAddress address = InetAddress.getByName("LAPTOP-IKV5PTCD");
        System.out.println(address);//LAPTOP-IKV5PTCD/172.20.10.6

        //public String getHostName()获取此 IP 地址的主机名。
        String name = address.getHostName();
        System.out.println(name);//LAPTOP-IKV5PTCD

        //获取具体的IP地址文本形式
        //public String getHostAddress()返回 IP 地址字符串(以文本表现形式)。
        String ip = address.getHostAddress();
        System.out.println(ip);//172.20.10.6
    }
}

二、UDP协议

1、发送端和接收端开发步骤

package org.westos_02_UDP协议;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

/**
 * UDP协议(发送端和接收端),不需要建立连接通道
 * 发送端 步骤: 
 * 1)创建UDP协议发送端的Socket对象 
 * 2)创建数据报包:通过这个数据包将数据发送到接收端 
 * 3)调用UDP协议发送端发送的方法
 * 4)关闭资源
 * 
 * @author 小鑫
 * 
 */
public class SendDemo {

    public static void main(String[] args) throws IOException  {

        //1) 创建Socket对象:DatagramSocket(客户端的套接字)
        // DatagramSocket:用来发送和接收数据报包的套接字。
        // public DatagramSocket() throws SocketException
        DatagramSocket ds = new DatagramSocket();// 创建了UDP协议的Socket对象

        // 发送一句话
        String str = "hello,word";

        // 2)创建数据报包对象
        // public DatagramPacket(byte[] buf, int length ,InetAddress address,int
        // port)
        // 将字符串数据转换成字节数组
        byte[] bys = str.getBytes();
        // 当前字节数组的实际长度
        int len = bys.length;

        // 创建InetAddress对象,Ip地址对象
        InetAddress address = InetAddress.getByName("172.20.10.6");

        // 指定端口号:0-65535是有效端口号
        int port = 12345;

        DatagramPacket dp = new DatagramPacket(bys, len, address, port);

        // 3)调用UDP协议DataScoket类里面发送的方法
        // public void send(DatagramPacket p) throws IOException从此套接字发送数据报包
        ds.send(dp);

        // 4)关闭资源
        ds.close();
    }
}
package org.westos_02_UDP协议;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

/**
 * UDP协议接收端:
 *   1)创建接收端Socket对象
 *   2)创建一个数据报包接收发送端发来的数据报包
 *   3)接收数据,调用DataSocket类中的接收方法接收数据
 *   4)解析数据报包里面的数据,显示
 *   5)关闭资源
 *   
 *多次运行接收端,会出现一处:BindException:绑定异常:
 *          接收端运行一次就可以了,端口号已经被占用了,不能再继续使用这个端口
 * @author 小鑫
 *
 */
public class ReceiveDemo {

    public static void main(String[] args) throws IOException  {

        //1)创建UDP协议Socket对象
        DatagramSocket ds = new DatagramSocket(12345);

        //2)创建数据报包:DatagramPacket,接收数据
        //public DatagramPacket(byte[] buf,int length)构造 DatagramPacket,用来接收长度为 length 的数据包。
        byte[] bys=new byte[1024];
        DatagramPacket dp = new DatagramPacket(bys, bys.length);

        //3)接收数据:public void receive(DatagramPacket p) throws IOException从此套接字接收数据报包
        ds.receive(dp);// 阻塞式方法(等待发送端发送数据,只要没有数据,就一直等待,有数据的话将数据显示控制)

        //4)解析
        //获取到ip字符串表现形式
        //public InetAddress getAddress():首先通过数据报包得到一个Ip地址对象:InetAddress
        InetAddress address = dp.getAddress();
        //可以通过getHostAddress()得到ip地址的文本形式
        String ip = address.getHostAddress();
        //byte[] getData() 返回数据缓冲区。 
        //int getLength() 返回将要发送或接收到的数据的长度。
        byte[] dataBys = dp.getData();
        int len = dp.getLength();
        //将字符串显示出来
        String str = new String(bys, 0, len);
        System.out.println(ip+"给你发送了"+str);
        //172.20.10.6给你发送了hello,word

        //5)关闭
        ds.close();
    }
}

2、改进版

package org.westos_03_改进UDP协议;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/**
 * UDP:发送端
 * @author 小鑫
 * 
 */
public class SendDemo {

    public static void main(String[] args) throws IOException {

        // 1)创建Socket对象
        DatagramSocket ds = new DatagramSocket();

        // 2)创建数据报包
        byte[] bys = "hello,world".getBytes();
        DatagramPacket dp = new DatagramPacket(bys, bys.length,
                InetAddress.getByName("172.20.10.6"), 8888);

        //3)将数据以数据报包发送出去
        ds.send(dp);

        //4)关闭资源
        ds.close();
    }
}
package org.westos_03_改进UDP协议;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

/**
 * UDp:接收端
 * @author 小鑫
 *
 */
public class ReceiveDemo {

    public static void main(String[] args) throws IOException {

        //1)创建Socket对象
        DatagramSocket ds = new DatagramSocket(8888);

        //2)创建接收容器:报包
        byte[] bys=new byte[1024];
        DatagramPacket dp = new DatagramPacket(bys, bys.length);

        //3)接收数据
        ds.receive(dp);

        //4)解析
        //获取IP地址字符串
        String ip = dp.getAddress().getHostAddress();
        //获取缓存区数据
        byte[] bys2 = dp.getData();
        //获取长度
        int len = dp.getLength();

        String s = new String(bys2, 0, len);
        System.out.println(ip+"发来了"+s);

        //5)关闭
        ds.close();
    }
}

3、发送端一直发送

package org.westos_04_键盘录入UDP协议;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/**
 * 发送端的数据来源不是简单的一条语句而是不停的键盘录入
 * 
 * @author 小鑫
 * 
 */
public class SendDemo {

    public static void main(String[] args) throws IOException {

        // 创建发送端Socket对象
        DatagramSocket ds = new DatagramSocket();

        // 以IO流的读取键盘录入的数据发送到接收端
        // 字符缓冲流
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        while ((line = br.readLine()) != null) {
            // 自定义结束条件
            if ("over".equals(line)) {
                break;
            }
            // 创建数据报包
            byte[] bys = line.getBytes();
            DatagramPacket dp = new DatagramPacket(bys, bys.length,
                    InetAddress.getByName("172.20.10.6"), 6666);
            //发送
            ds.send(dp);    
        }
        //释放资源
        ds.close();
    }
}
package org.westos_04_键盘录入UDP协议;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

/**
 * 接收端不停的接收键盘录入的数据显示到控制台上
 * @author 小鑫
 *
 */
public class ReceiveDemo {

    public static void main(String[] args) throws IOException {

        //创建接收端Socket对象
        DatagramSocket ds = new DatagramSocket(6666);
        while(true){
            byte[] bys=new byte[1024];
            DatagramPacket dp = new DatagramPacket(bys, bys.length);

            //接收数据
            ds.receive(dp);
            //获取ip
            String ip = dp.getAddress().getHostAddress();
            //解析
            byte[] buff = dp.getData();
            int len = dp.getLength();
            String s = new String(buff, 0, len);
            System.out.println(ip+"发来了"+s);
            //模仿发送端一直发送数据,不用关闭资源
        }
    }
}

4、多线程UDP通信

package org.westos_05_多线程_键盘录入UDP协议;

import java.net.DatagramSocket;
import java.net.SocketException;

/**
 * 需求:接收端和发送端是在两个窗口中显示的,如何让这两个接收端和发送端处于一个窗口下(main中) (使用多线程第二种方式:Runable接口的方式实现
 * 发送端和接收端处于一个主线程中)
 * 
 * @author 小鑫
 * 
 */
public class ChatRoom {

    public static void main(String[] args) {

        try {
            // 创建发送端和接收端Socket对象
            DatagramSocket sendSocket = new DatagramSocket();
            DatagramSocket receiveSocket = new DatagramSocket(8866);

            // 创建资源对象
            SendThread st = new SendThread(sendSocket);
            ReceiveThread rt = new ReceiveThread(receiveSocket);

            //创建线程类对象
            Thread t1 = new Thread(st);
            Thread t2 = new Thread(rt);
            //启动线程
            t1.start();
            t2.start();
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }
}
package org.westos_05_多线程_键盘录入UDP协议;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class SendThread implements Runnable {

    // 定义一个变量
    private DatagramSocket ds;

    public SendThread(DatagramSocket ds) {
        this.ds = ds;
    }

    @Override
    public void run() {
        try {
            // 创建发送端Socket对象
            // IO流读取键盘录入数据
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String line = null;
            while ((line = br.readLine()) != null) {

                //结束条件
                if("over".equals(line)){
                    break;
                }
                // 创建数据报包
                byte[] bys = line.getBytes();
                DatagramPacket dp = new DatagramPacket(bys, bys.length,
                        InetAddress.getByName("192.168.100.15"), 8866);
                //发送
                ds.send(dp);
            }
        } catch (IOException e) {           
            e.printStackTrace();
        }finally{
            //释放资源
            if(ds!=null){
                ds.close();
            }
        }

    }

}
package org.westos_05_多线程_键盘录入UDP协议;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class ReceiveThread implements Runnable{

    private DatagramSocket ds;
    public ReceiveThread(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);
            //获取IP文本表现形式
            String ip = dp.getAddress().getHostAddress();
            //解析
            byte[] buff = dp.getData();
            int len = dp.getLength();
            String s = new String(buff, 0, len);
            System.out.println(ip+"发来了"+s);
            }           
        } catch (IOException e) {
            e.printStackTrace();
        }
        //接收要不停接收数据,不需要关闭
    }

}

三、TCP协议

1、TCP协议客户端和发送端开发

package org.westos_06_TCP协议;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

/**
 * 使用Socket编程里面的TCP协议:
 * 客户端和服务器端的交互 客户端步骤: 
 * 1)创建客户端的socket对象 (客户端套接字流的形式)
 * 2)获取通道的内流(输出流) 
 * 3)使用输出流对象写数据 
 * 4)关闭客户端的Socket对象
 * 
 * 对于TCP协议来说:客户端和服务器端是需要建立连接通道的,如果没有启动服务器端,先启动客户端: 报异常:java.net.ConnectException
 * Connection refused: connect :连接被拒绝!
 * 
 * @author 小鑫
 * 
 */
public class CilentDemo {

    public static void main(String[] args) throws IOException {
        // 1)创建客户端Socket对象:此类实现客户端套接字
        // public Socket(InetAddress address, int port)throws
        // IOException创建一个流套接字并将其连接到指定 IP 地址的指定端
        // Socket s = new Socket(InetAddress.getByName("192.168.100.15"), 12345);

        // public Socket(String host, int port)
        // host:可以是主机名称也可是ip地址的字符串表现形式
        Socket s = new Socket("192.168.100.15", 12345);

        // 2)获取通道内的输出流
        // public OutputStream getOutputStream()throws IOException返回此套接字的输出流。
        OutputStream out = s.getOutputStream();

        //3)客户端通道流给服务器写数据
        out.write("hello,world".getBytes());

        //4)关闭客户端Socket
        s.close();
    }
}
package org.westos_06_TCP协议;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * TCP协议服务器端
 *   1)创建服务器端的socket对象,指定端口
 *   2)服务器端需要监听客户端的连接
 *   3)获取通道内的输入流
 *   4)将数据获取到并显示到控制台
 *   5)关闭服务器端的socket资源
 * @author 小鑫
 *
 */
public class ServerDemo {

    public static void main(String[] args) throws IOException {
        //1)public ServerSocket(int port) 构造方法:创建绑定到特定端口的服务器套接字
        ServerSocket ss = new ServerSocket(12345);
        System.out.println("等待客户端连接...");
        //2)监听客户端
        //public Socket accept() throws IOException侦听并接受到此套接字的连接
        Socket s = ss.accept();
        System.out.println("客户端连接成功");
        //3)获取通道内的输入流对象
        //public InputStream getInputStream()
        InputStream in = s.getInputStream();
        //4)将客户端发送数据显示控制台
        byte[] bys=new byte[1024];
        //获取到实际的字节数  (阻塞式方法)
        int len = in.read(bys);
        String str = new String(bys, 0, len);
        //获取IP地址文本表现形式
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip+"发送来"+str);
        //5)关闭服务器端
        s.close();
    }
}

2、服务器端反馈

package org.westos_07_TCP协议_反馈数据;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * 客户端发送数据,服务器端给客户端反馈数据...
 * @author 小鑫
 *
 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {

        //创建客户端Socket对象
        Socket s = new Socket("192.168.100.15", 9999);
        //获取通道内的输出流
        OutputStream out = s.getOutputStream();
        //发送服务端,写入通道
        out.write("你很好".getBytes());
        //获取反馈过来的数据,获取通道输入流对象
        InputStream in = s.getInputStream();
        //读数据
        byte[] bys=new byte[1024];
        int len = in.read(bys);
        String client = new String(bys, 0, len);
        System.out.println(client);

        //关闭资源
        s.close();
    }
}
package org.westos_07_TCP协议_反馈数据;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerDemo {

    public static void main(String[] args) throws IOException {

        //1)获取Socket对象
        ServerSocket ss = new ServerSocket(9999);
        System.out.println("正在等待客户端连接");
        //2)监听客户端
        Socket s = ss.accept();
        //阻塞式方法结束,连接了(侦听到客户端的和的服务器端端口一致)
        System.out.println("客户端已连接");
        //3)获取通道内输入流
        InputStream in = s.getInputStream();
        byte[] bys=new byte[1024];
        int len = in.read(bys);
        String server = new String(bys, 0, len);
        System.out.println(server);
        //反馈,获取通道输出流
        OutputStream out = s.getOutputStream();
        out.write("收到数据".getBytes());
        //关闭资源
        s.close();
    }
}

3、客户端键盘录入

package org.westos_08_TCP协议键盘录入_反馈数据;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

/**
 * 客户端键盘录入数据
 * 
 * @author 小鑫
 * 
 */
public class ClientDemo {

    public static void main(String[] args) throws IOException {

        // 1)创建服务器端Socket对象
        Socket s = new Socket("192.168.100.15", 2468);
        // 2)键盘录入
        // BufferedReader字符流封装数据,读取键盘录入的数据
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        // 3)获取通道输出流,使用字符缓冲输出流封装通道内的流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                s.getOutputStream()));
        //BufferedReader一次读取一行数据:readLine
        String line=null;
        while((line=br.readLine())!=null){
            //定义结束条件
            if("over".equals(line)){
                break;
            }
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        //关闭资源
        s.close();
    }
}
package org.westos_08_TCP协议键盘录入_反馈数据;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerDemo {

    public static void main(String[] args) throws IOException {

        // 创建Socket对象
        ServerSocket ss = new ServerSocket(2468);
        System.out.println("等待客户端连接");
        // 监听客户端
        Socket s = ss.accept();
        System.out.println("客户端连接成功");
        // 封装服务器通道输入流
        BufferedReader br = new BufferedReader(new InputStreamReader(
                s.getInputStream()));
        String line=null;
        while((line=br.readLine())!=null){
            System.out.println(line);
        }

        //关闭资源
        s.close();
    }
}

4、客户端键盘录入,服务器输出将录入的内容输出到文本文件

package org.westos_09_TCP协议键盘录入输出文本文件;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * 客户端键盘录入,服务器输出将录入的内容输出到文本文件
 * 
 * @author 小鑫
 * 
 */
public class ClientDemo {

    public static void main(String[] args) throws IOException {

        // 创建客户端Socket对象
        Socket s = new Socket("192.168.100.15", 1357);
        // 键盘录入
        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("over".equals(line)){
                break;
            }
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        s.close();
    }
}
package org.westos_09_TCP协议键盘录入输出文本文件;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerDemo {

    public static void main(String[] args) throws IOException {

        // 创建Socket对象
        ServerSocket ss = new ServerSocket(1357);
        // 监听客户端
        Socket s = ss.accept();
        // 获取通道输入流
        BufferedReader br = new BufferedReader(new InputStreamReader(
                s.getInputStream()));
        // 服务器输出一个文本文件
        BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
        String line=null;
        while((line=br.readLine())!=null){
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        s.close();
        bw.close();
    }
}

5、客户端一个文本文件,服务器端将客户端文本文件中的内容展示到控制台上

package org.westos_10_TCP协议客户端文本文件服务器端输出;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * 客户端一个文本文件,服务器端将客户端文本文件中的内容展示到控制台上
 * 
 * @author 小鑫
 * 
 */
public class ClientDemo {

    public static void main(String[] args) throws IOException {

        // 创建Socket对象
        Socket s = new Socket("192.168.100.15", 4567);
        // 封装文件
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));
        // 获取通道输出流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                s.getOutputStream()));
        String line=null;
        while((line=br.readLine())!=null){
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        //释放资源
        br.close();
        s.close();
    }
}
package org.westos_10_TCP协议客户端文本文件服务器端输出;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerDemo {

    public static void main(String[] args) throws IOException {

        // 创建服务器端Socket对象
        ServerSocket ss = new ServerSocket(4567);
        // 监听客户端
        Socket s = ss.accept();
        // 获取通道输入流
        BufferedReader br = new BufferedReader(new InputStreamReader(
                s.getInputStream()));
        //一次读取一行
        String  line=null;
        while((line=br.readLine())!=null){
            System.out.println(line);
        }
        s.close();
    }
}

6、客户端发送文本文件,服务器端复制到文本文件中

package org.westos_01_TCP协议客户端文本文件服务器端复制到另一文本文件;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class UploadClient {

    public static void main(String[] args) throws IOException {

        // 创建客户端Socket对象
        Socket s = new Socket("192.168.100.15", 3456);
        // 封装文件
        BufferedReader br = new BufferedReader(
                new FileReader("ClientDemo.java"));
        // 获取通道输出流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                s.getOutputStream()));
        String line=null;
        while((line=br.readLine())!=null){
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        //释放资源
        s.close();
        br.close();
    }
}
package org.westos_01_TCP协议客户端文本文件服务器端复制到另一文本文件;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class UploadClient {

    public static void main(String[] args) throws IOException {

        // 创建客户端Socket对象
        Socket s = new Socket("192.168.100.15", 3456);
        // 封装文件
        BufferedReader br = new BufferedReader(
                new FileReader("ClientDemo.java"));
        // 获取通道输出流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                s.getOutputStream()));
        String line=null;
        while((line=br.readLine())!=null){
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        //释放资源
        s.close();
        br.close();
    }
}

7、客户端发送文本文件,服务器端将文本文件中的内容复制输出到一个新的文本文件中, 并反馈

package org.westos_02_TCP协议客户端文本文件服务器端复制文本文件并反馈;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

/**
 * 客户端文本文件,服务器端将文本文件中的内容复制输出到一个新的文本文件中, 并且服务器端反馈给客户端,文件复制成功了... public void
 * shutdownOutput() throws IOException禁用此套接字的输出流
 * 
 * @author 小鑫
 * 
 */
public class UploadClient {

    public static void main(String[] args) throws IOException {

        // 创建Socket对象
        Socket s = new Socket("192.168.100.15", 6666);
        // 封装数据源
        BufferedReader br = new BufferedReader(
                new FileReader("ClientDemo.java"));
        // 获取通道输出流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                s.getOutputStream()));
        String line = null;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        // 读完了反馈
        s.shutdownOutput();
        // 获取通道输入流读取服务器反馈
        BufferedReader brClient = new BufferedReader(new InputStreamReader(
                s.getInputStream()));
        String fk = br.readLine();
        System.out.println(fk);
        //释放资源
        s.close();
        br.close();
    }
}
package org.westos_02_TCP协议客户端文本文件服务器端复制文本文件并反馈;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class UploadServer {

    public static void main(String[] args) throws IOException {

        // 创建Socket对象
        ServerSocket ss = new ServerSocket(6666);
        // 监听客户端
        Socket s = ss.accept();
        // 获取通道输入流
        BufferedReader br = new BufferedReader(new InputStreamReader(
                s.getInputStream()));
        // 文本复制
        BufferedWriter bw = new BufferedWriter(new FileWriter("Copy2.java"));
        String line = null;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        // 反馈,获取通道内输出流对象
        BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(
                s.getOutputStream()));
        bw.write("文件复制完了");
        bw.newLine();
        bw.flush();
        //关闭资源
        s.close();
        bw.close();
    }
}

8、客户端的图片文件,服务器端输出一个图片文件并且给出反馈

package org.westos_03_TCP协议客户端发送图片服务器并反馈;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * 客户端的图片文件,服务器端输出一个图片文件并且给出反馈
 * 
 * @author 小鑫
 * 
 */
public class UploadClient {

    public static void main(String[] args) throws IOException {

        // 创建客户端Socket对象
        Socket s = new Socket("192.168.100.15", 7777);
        // 封装文件,字节流
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
                "林青霞.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);
        System.out.println(new String(bys2, 0, len2));

        //关闭
        s.close();
        bis.close();
    }
}
package org.westos_02_TCP协议客户端文本文件服务器端复制文本文件并反馈;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class UploadServer {

    public static void main(String[] args) throws IOException {

        // 创建Socket对象
        ServerSocket ss = new ServerSocket(6666);
        // 监听客户端
        Socket s = ss.accept();
        // 获取通道输入流
        BufferedReader br = new BufferedReader(new InputStreamReader(
                s.getInputStream()));
        // 文本复制
        BufferedWriter bw = new BufferedWriter(new FileWriter("Copy2.java"));
        String line = null;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        // 反馈,获取通道内输出流对象
        BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(
                s.getOutputStream()));
        bw.write("文件复制完了");
        bw.newLine();
        bw.flush();
        //关闭资源
        s.close();
        bw.close();
    }
}

day23

反射机制

反射机制:
反射就是通过获取到该类的字节码文件对象—->Class类对象,通过Class类对象获取该类里面的一些属性(成员变量),构造方法,成员方法等。
面试题:如何获取类的字节码文件对象,并且有几种方式呢?
* 1)Object类中的getClass()方法,表示正在运行的那个类:Class类
* 2)数据类型的class属性 举例:String.class,Student.class
* 3)Class类中的特有方法: public static Class

package org.westos_04_反射机制;

public class Person {

    private String name;
    int age;
    public String address;

    //无参构造
    public Person(){}

    //私有化构造方法
    private Person(String name){
        this.name=name;
    }

    //有参构造
    Person(String name,int age){
        this.name = name ;
        this.age = age ;
    }

    public Person(String name,int age,String address){
        this.name = name ;
        this.age =age ;
        this.address = address ;
    }

    //成员方法
    public void show(){
        System.out.println("show");
    }

    public void method(String s){
        System.out.println("method"+s);
    }

    public String getString(String s, int i) {
        return s + "---" + i;
    }

    private void function(){
        System.out.println("function");
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + ", address=" + address
                + "]";
    }


}

2、反射的三种表现形式

package org.westos_04_反射机制;

/**
 * 反射机制: 反射就是通过获取到该类的字节码文件对象---->Class类对象,
 * 通过Class类对象获取该类里面的一些属性(成员变量),构造方法,成员方法:
 * @author 小鑫
 * 
 */
public class Demo1 {

    public static void main(String[] args) throws ClassNotFoundException {

        // 第一种方式:
        // 创建Person对象
        Person p1 = new Person();
        Class c1 = p1.getClass();// ---->得到Person.class字节码文件对象
        Person p2 = new Person();
        Class c2 = p2.getClass();// ------->Person.class字节码文件对象

        System.out.println(p1 == p2);// false
        System.out.println(c1 == c2);// true

        // 第二种方式
        Class c3 = Person.class;
        System.out.println(c3 == c1);// true

        // 第三种方式
        //参数需要类路径:类的全路径名称
        Class c4 = Class.forName("org.westos_04_反射机制.Person");
        System.out.println(c4==c1);//true
    }
}

3、获取构造方法

package org.westos_05_反射机制_获取成员方法;

import java.lang.reflect.Constructor;

/**
 * org.westos_04_反射机制
 * @author 小鑫
 *
 */
public class ReflectDemo {

    public static void main(String[] args) throws Exception {

        //获取一个类中的构造方法,首先找到这个类的class文件对象,通过反射
        Class c = Class.forName("org.westos_04_反射机制.Person");

        //使用该Class类对象中的一些成员方法:
        //public Constructor<?>[] getConstructors(),返回的是一个构造方法所在数组
        //public Constructor<?>[] getDeclaredConstructors():获取的是当前字节码文件对象中所有的构造方法
        Constructor[] con1 = c.getConstructors();
        for(Constructor constructor1:con1){
            System.out.println(constructor1);
            //public org.westos_04_反射机制.Person(java.lang.String,int,java.lang.String)
            //public org.westos_04_反射机制.Person()
        }

        //获取当前Pereson类中所有的构造方法
        Constructor[] con2 = c.getDeclaredConstructors();
        for(Constructor constructor2:con2){
            System.out.println(constructor2);
            //public org.westos_04_反射机制.Person(java.lang.String,int,java.lang.String)
            //org.westos_04_反射机制.Person(java.lang.String,int)
            //private org.westos_04_反射机制.Person(java.lang.String)
            //public org.westos_04_反射机制.Person()
        }

        //获取单个的构造方法:public Constructor<T> getConstructor(Class<?>... parameterTypes)
        //返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法
        //参数表示:参数数据类型的字节码文件对象:获取指定构造方法里面有参数,需要写上数据类型的字节码文件对象
        //获取构造器对象:Constructor
        Constructor con3 = c.getConstructor();
        //public T newInstance(Object... initargs):传递的是实际参数
        Object obj = con3.newInstance();
        System.out.println(obj);//Person [name=null, age=0, address=null]

    }
}

4、 通过反射获取构造方法并且给成员属性赋值

package org.westos_05_反射机制_获取成员方法;

import java.lang.reflect.Constructor;

/**
 * 通过反射获取构造方法并且给成员属性赋值
 * 
 * @author 小鑫
 * 
 */
public class ReflectDemo2 {

    public static void main(String[] args) throws Exception {

        // 获取Person类的字节码文件对象
        Class c = Class.forName("org.westos_04_反射机制.Person");

        // 通过反射获取指定构造方法:getConstructor(Class ...parameterTyps) 参数:参数类型.class
        Constructor con = c.getConstructor(String.class, int.class,
                String.class);
        //创建构造器的实例对象,来给他指定的字节码文件对象里面的成员变量赋值
        Object obj = con.newInstance("张三",30,"南海");
        System.out.println(obj);
        //Person [name=张三, age=30, address=南海]
    }
}

5、通过反射获取私有的构造方法,并使用

package org.westos_05_反射机制_获取成员方法;

import java.lang.reflect.Constructor;

/**
 * 通过反射获取私有的构造方法,并使用
 * @author 小鑫
 *
 */
public class ReflectDemo3 {

    public static void main(String[] args) throws Exception {

        //1)获取Person类的字节码文件对象
        Class c = Class.forName("org.westos_04_反射机制.Person");
        //2)获取私有方法
        //该方法获取当前指定的公共的构造方法
        //public Constructor<T> getConstructor(Class<?>... parameterTypes)
        //表示获取类或者接口中的指定的构造方法
        //public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
        Constructor con = c.getDeclaredConstructor(String.class);
        //public void setAccessible(boolean flag):在访问的时候取消java语言访问检查(强制性)
        //将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查
        con.setAccessible(true);
        Object obj = con.newInstance("张三");
        System.out.println(obj);
        //Person [name=张三, age=0, address=null]

    }
}

6、反射获取成员变量并使用:Field

package org.westos_05_反射机制_获取成员方法;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

/**
 * 通过反射获取成员变量并使用:Field
 * Declared:反射私有的成员变量,成员方法,类的关键字
 * @author 小鑫
 *
 */
public class ReflectDemo4 {

    public static void main(String[] args) throws Exception {

        //1)通过反射获取字节码文件对象
        Class c = Class.forName("org.westos_04_反射机制.Person");
        //2)获取所有的公共的成员变量
        //public Field[] getFields():所有的公共的可访问的字段,返回的是Field对象数组
        //public Field[] getDeclaredFields():获取当前字节码文件对象中所有的公共的或者私有的字段
        Field[] fields = c.getFields();
        Field[] declaredFields = c.getDeclaredFields();
        for(Field f:fields){
            System.out.println(f);
            //public java.lang.String org.westos_04_反射机制.Person.address

        }
        //赋值
        //获取构造器对象
        Constructor con = c.getConstructor();
        //构建构造器实例
        Object obj = con.newInstance();
        System.out.println(obj);
        //Person [name=null, age=0, address=null]

        //给address赋值并使用
        //public Field getField(String name):获取公共的指定的字段  参数为当前成员变量名称"address"
        Field addressField = c.getField("address");
        //将指定对象变量上此 Field 对象表示的字段设置为指定的新值public void set(Object obj, Object value)
        //给obj实例对象里面的成员变量设置一个实际参数---->value
        addressField.set(obj, "北京");
        System.out.println(obj);//Person [name=null, age=0, address=北京]
        //给name赋值并使用
        Field nameField = c.getDeclaredField("name");
        nameField.setAccessible(true);//取消Java语言访问检查
        nameField.set(obj, "张三");
        System.out.println(obj);//Person [name=张三, age=0, address=北京]
        //给age赋值并使用
        Field ageField = c.getDeclaredField("age");
        ageField.setAccessible(true);//取消Java语言访问检查
        ageField.set(obj, 30);
        System.out.println(obj);//Person [name=张三, age=30, address=北京]
    }
}

7、通过反射获取成员变量并使用

package org.westos_05_反射机制_获取成员方法;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
 * 通过反射获取成员变量并使用
 * 
 * @author 小鑫
 * 
 */
public class ReflectDemo5 {

    public static void main(String[] args) throws Exception {

        // 通过反射获取字节码文件对象并使用
        Class c = Class.forName("org.westos_04_反射机制.Person");
        /*// 获取成员方法(Method)
        // public Method[] getMethods():获取当前该字节码文件对象(Person.class)中自己本身以及它父类中所有的公共成员方法
        Method[] methods = c.getMethods() ;
        // public Method[] getDeclaredMethods():获取当前字节码文件对象本身所有的成员方法
        Method[] methods2 = c.getDeclaredMethods() ;
         for(Method m :methods2){
             System.out.println(m);
         }*/
        //获取构造器对象,通过构造器创建当前字节码文件的实例对象
        Constructor con = c.getConstructor();
        Object obj = con.newInstance();//Person对象
        //获取单个方法
        //public void show() {}
        /**
         * public Method getMethod(String name,Class<?>... parameterTypes):指定公共成员方法
         * 参数1:表示方法名
         * 参数2:该方法的参数类型的Class对象(数据类型的class属性) String.class
         */
        Method m1 = c.getMethod("show");
        /**
         * public Object invoke(Object obj, Object... args)
         * 参数1:表示当前针对哪个以实例对象进行方法的调用
         * 参数2:当前调用该方法的时候里面传递的实际参数
         */
        m1.invoke(obj);

        //public void method(String s){}
        Method m2 = c.getMethod("method", String.class);
        m2.invoke(obj, "nihao");

        /**
         * public String getString(String s, int i) {
                return s + "---" + i;
           }
         */
        Method m3 = c.getMethod("getString", String.class,int.class);
        String objString =(String) m3.invoke(obj, "hello",10);

        // private void function(){
        // System.out.println("function");
        // }
        //该方法是私有的,public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
        Method m4 = c.getDeclaredMethod("function");
        m4.setAccessible(true);//取消Java语言访问检查
        m4.invoke(obj);
    }
}

8、用户操作

package org.westos_06_handler;

/**
 * 用户测试类
 * @author 小鑫
 *
 */
public class UserDaoDemo {

    public static void main(String[] args) {

        //创建用户操作对象
        UserDao ud = new UserDaoImpl1();
        ud.add();
        ud.delete();
        ud.update();
        ud.serach();
        System.out.println("-----------");
        UserDao ud2 = new UserDaoImpl2() ;
        ud2.add() ;
        ud2.delete() ;
        ud2.update() ;
        ud2.serach() ;
    }
}
package org.westos_06_handler;

//用户操作接口
public interface UserDao {

    // 增
    public abstract void add();

    // 删
    public abstract void delete();

    // update:修改
    public abstract void update();

    // 查
    public abstract void serach();
}
package org.westos_06_handler;

public class UserDaoImpl1 implements UserDao {

    @Override
    public void add() {
        System.out.println("增加功能");
    }

    @Override
    public void delete() {
        System.out.println("删除功能");
    }

    @Override
    public void update() {
        System.out.println("修改功能");
    }

    @Override
    public void serach() {
        System.out.println("查询功能");
    }

}
package org.westos_06_handler;

public class UserDaoImpl2 implements UserDao {

    @Override
    public void add() {
        System.out.println("权限校验");
        System.out.println("添加功能");
        System.out.println("日志记录");
    }

    @Override
    public void delete() {
        System.out.println("权限校验");
        System.out.println("添加功能");
        System.out.println("日志记录");
    }

    @Override
    public void update() {
        System.out.println("权限校验");
        System.out.println("添加功能");
        System.out.println("日志记录");
    }

    @Override
    public void serach() {
        System.out.println("权限校验");
        System.out.println("添加功能");
        System.out.println("日志记录");
    }

}

9、代理对象

package org.westos_06_handler2;

import java.lang.reflect.Proxy;

public class UserTest {

    public static void main(String[] args) {

        // 创建用户操作的对象
        UserDao ud = new UserDaoImpl();
        ud.add();
        ud.delete();
        ud.update();
        ud.serach();

        // 给ud对象设置代理对象
        // Proxy类中的方法创建动态代理类对象
        // public static Object newProxyInstance
        // (ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
        // InvocationHandler是代理对象需要实现的接口---->需要自定义一个类实现这个接口
        // 创建代理对象
        MyInvocation handle = new MyInvocation(ud);
        UserDao proxy = (UserDao) Proxy.newProxyInstance(ud.getClass()
                .getClassLoader(), ud.getClass().getInterfaces(), handle);
        //参数1:需要类加载器:首先获取当前目标对象的字节码文件对象,在去调用getClassLoser()
        //参数2:获取目标的字节码文件对象,调用方法得到给目标对象提供一组接口

        proxy.add();
        proxy.delete() ;
        proxy.update() ;
        proxy.serach() ;

    }
}
package org.westos_06_handler2;

//用户操作的接口
public interface UserDao {

    //增
    public abstract void add() ;
    //删
    public abstract void delete() ;
    //update:修改
    public abstract void update() ;
    //查
    public abstract void serach() ;
}
package org.westos_06_handler2;

public class UserDaoImpl implements UserDao {

    @Override
    public void add() {
        System.out.println("增加功能");
    }

    @Override
    public void delete() {
        System.out.println("删除功能");
    }

    @Override
    public void update() {
        System.out.println("修改功能");
    }

    @Override
    public void serach() {
        System.out.println("查询功能");
    }

}

package org.westos_06_handler2;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocation implements InvocationHandler{

    //目标对象
    private Object target;

    //无参构造
    public MyInvocation(Object target) {
        this.target=target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("权限校验");
        Object result = method.invoke(target, args);
        System.out.println("日志记录");
        return result;//返回值就是代理对象
    }



}

10、反射的应用:集中中添加元素

package org.westos_07_test;

import java.lang.reflect.Method;
import java.util.ArrayList;

/**
 * ArrayList<Integer>的一个对象,在这个集合中添加一个字符串数据
 * @author 小鑫
 *
 */
public class ArrayListTest {

    public static void main(String[] args) throws Exception {

        ArrayList<Integer> array = new ArrayList<Integer>();
        //利用反射类来给集合中添加字符串数据
        array.add(100);
        Class c = array.getClass();
        Method m = c.getMethod("add", Object.class);
        m.invoke(array, "hello");
        m.invoke(array, "world");
        m.invoke(array, "java");
        System.out.println(array);
        //[100, hello, world, java]

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值