第三十一天

今天内容

1.UDP发送端可以不断键盘录入数据,接收端不断展示数据,发送可以自定义结束条件 (课堂练习)

发送端

import javafx.scene.layout.BackgroundFill;

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 高圆圆

  • @date 2022/11/28 9:58

  • 需求:

  • UDP发送端可以不断键盘录入数据,接收端不断展示数据,

  • 发送端可以自定义结束条件 (课堂练习) */ public class UdpSend {

    public static void main(String[] args) { //UDP发送端可以不断键盘录入数据

    //创建发送端的socket
    DatagramSocket ds = null ;
    try {
       ds = new DatagramSocket() ;
        //键盘录入可以使用BufferedReader--->读一行
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in)) ;
        String line = null ;
        //一次读一行内容
        System.out.println("请您输一个数据");
        while((line=br.readLine())!=null){
            if("over".equals(line)){
                break;
            }
            //创建数据报包,将数据存储在数据包中
            DatagramPacket dp = new DatagramPacket(line.getBytes()
            ,line.getBytes().length,
            InetAddress.getByName("10.35.162.121"),
                    6666) ;
            //发送数据报包
            ds.send(dp) ;
        }
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        if(ds!=null){
            ds.close() ;
        }
    }}}

    接收端

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

/**

  • @author 高圆圆

  • @date 2022/11/28 10:09

  • 接收端不断展示数据------->接收端模拟真实,不需要关闭 */ public class UdpReceive { public static void main(String[] args) {

     try {
         //创建接收端的Socket对象
         DatagramSocket ds = new DatagramSocket(6666) ;
     
         while(true){
             //创建一个接收容器
             //自定义一个字节数组缓冲区
             byte[] buffer = new byte[1024] ;
             int bufferLength =  buffer.length ;
             DatagramPacket dp = new DatagramPacket(buffer,bufferLength) ;
             //接收数据容器
             ds.receive(dp) ;
     
             //解析接收容器中真实内容
             byte[] bytes = dp.getData();
             int length = dp.getLength();
             //每次0开始读取字节数---转成String
             String receiveMsg = new String(bytes,0,length) ;
     
             //获取ip地址字符串
             String ip = dp.getAddress().getHostAddress() ;
             //展示数据
             System.out.println("data from-->"+ip+",conent is :"+receiveMsg);
         }
     } catch (IOException e) {
         e.printStackTrace();
     }}}

2.TCP客户端和服务器端的代码实现

服务器端

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
​
public class Tcp_server {
    public static void main(String[] args) throws IOException {
        //创建服务端对象
        ServerSocket ss=new ServerSocket(8888);
        System.out.println("服务器正在等待客户端连接请求...");
        //监听客户端的连接
        Socket socket=ss.accept();
        System.out.println("客户端已连接");
        //获取监听到的客户端的通道内的字节输入流对象,读数据
        InputStream inputStream=socket.getInputStream();
        //一次读取一个字节数组
        byte[] bytes=new byte[1024];
        int length=inputStream.read(bytes);
        //转换String
        String s=new String(bytes,0,length);
        //获取ip地址对象,同时打印出ip地址字符串形式
        String ip=socket.getInetAddress().getHostAddress();
        System.out.println("data from--->"+ip+"content is--->"+s);
        //服务器端反馈给客户端数据
        //服务器可以获取监听客户端通道内字节输出流,写数据
        OutputStream outputStream=socket.getOutputStream();
        outputStream.write("已收到数据".getBytes());
        //释放服务器端的资源
        ss.close();
    }
}

客户端

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
​
public class Tcp_client {
    public static void main(String[] args) throws IOException {
        //创建客户端对象,指定ip和端口
        Socket socket=new Socket("127.0.0.1",8888);
        //获取客户端通道内容字节输出流对象,写数据
        OutputStream outputStream=socket.getOutputStream();
        outputStream.write("纵使苍天陨落,契约必须完成".getBytes());
​
​
        //客户端获取通道字节输入流对象,读服务器的反馈的数据
        InputStream inputStream=socket.getInputStream();
        byte[] bytes=new byte[1024];
        int length=inputStream.read(bytes);
        String s=new String(bytes,0,length);
        System.out.println(s);
        //释放资源
        outputStream.close();
    }
}

3.TCP三次握手的原理--->SYNC+ACK

SYNC同步序列编号
ACK:消息确认字符(当客户端发送数据到服务器端,服务器需要 确认并反馈)

4.TCP的应用

4.1 TCP方式,客户端可以不断键盘录入数据,服务器端不断展示数据

//客户端 import java.io.*; import java.net.Socket;

//TCP客户端不断键盘录入数据,服务器端不断展示数据在控制台 public class Test5_client { public static void main(String[] args) throws IOException { //创建TCP客户端对象 Socket socket=new Socket("127.0.0.1",5555); //将录入的数据转为字符流输入对象 BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(System.in)); //客户端输出的字节流转为字符流,通道内的字节流封装成字符流 BufferedWriter bufferedWriter=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); //录入一行,输出一行 String s=null; while ((s=bufferedReader.readLine())!=null){ bufferedWriter.write(s); bufferedWriter.newLine(); bufferedWriter.flush(); } socket.shutdownOutput(); InputStream inputStream=socket.getInputStream(); byte[] bytes=new byte[1024]; int len=inputStream.read(bytes); System.out.println("录入结束"); //关闭资源 socket.close(); bufferedReader.close(); } } //服务端 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket;

public class Test5_server { public static void main(String[] args) throws IOException { //创建服务端对象 ServerSocket serverSocket=new ServerSocket(5555); //监听客户端连接 Socket socket=serverSocket.accept(); //将读入的字节流输入数据封装成字符流,将通道内的字节流输入转为字节流输入 BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream())); //将读入的字符流数据输出到控制台 String line=null; while ((line=bufferedReader.readLine())!=null){ System.out.println(line); } serverSocket.close(); } }

4.2 TCP客户端的读取文本文件(将文本文件写入通道中)_,

服务器端复制文本文件到指定路径中(将文本文件写入指定文件中)

客户端

import java.io.*; import java.net.Socket;

/**

  • @author 高圆圆

  • @date 2022/11/28 14:27

  • 需求:

  • TCP客户端的文本文件(当前项目下的UdpReceive.java文件)

  • 分析:TCP创建字符缓冲输入流--->读UdpReceive.java文件 一次读一行

  • TCP客户端获取通道字节输入流--->封装字符缓冲输出流--->写一行---发给服务器端 * * */

    public class TcpClientTest {
    public static void main(String[] args) throws IOException {
        //创建客户端的Socket对象
        Socket s = new Socket("10.35.162.121",2222) ;
        //创建字符缓冲输入流对象
        BufferedReader br = new BufferedReader(
                new FileReader("UdpReceive.java")) ;

    //获取客户端通道的字节输出流---->包装成BufferedWriter:字符缓冲输出流
    BufferedWriter bw = new BufferedWriter(
            new OutputStreamWriter(s.getOutputStream())) ;
    ​
    //每次从.java文件读取一行,给通道流的流中写一行
    String line = null ;
    while((line=br.readLine())!=null){
        bw.write(line) ;
        bw.newLine();
        bw.flush();
    }
    System.out.println("文件读完,发送过去了...");
    //释放资源
    br.close();
    s.close();
    }}

    服务端

    import java.io.*; import java.net.ServerSocket; import java.net.Socket;

    /**

    • @author 高圆圆

    • @date 2022/11/28 14:27

    • TCP服务器端将复制客户端的文件内容,复制到D://2211//day27_code_resource//Copy.java里面

    • 分析:

    • TCP获取监听客户端的字节输入流--->封装字符缓冲输入流--->一读取一行

    • 创建字符缓冲输出流--->写一行D://2211//day27_code_resource//copy.java到这个文件中 */

      public class TcpServerTest {
      public static void main(String[] args) throws IOException {
          //创建服务器端的Socket对象
          ServerSocket ss = new ServerSocket(2222) ;
          //监听客户端连接
          Socket s = ss.accept();
          //获取监听客户端所在的通道内字节输入流对象---->包装成字符缓冲输入流
          BufferedReader br = new BufferedReader(
                  new InputStreamReader(s.getInputStream())) ;
      //将监听客户端的通道内的字节流(已经被包装了字符缓冲输入流)的内容----通过的字符缓冲输出流写入到文件中
      BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\EE_2211\\day27_code_resource\\copy.java")) ;
      //一次读取一行,写一行到文件中
      String line = null ;
      while((line=br.readLine())!=null){
          bw.write(line);
          bw.newLine();
          bw.flush();
      }
      ​
      System.out.println("复制完毕");
      //释放资源
      bw.close();
      ss.close();
      }}

4.3 TCP客户端读取文本文件,服务器端复制文本文件,现在服务器端反馈给客户端,"已经复制完毕"

服务端

import java.io.*; import java.net.ServerSocket; import java.net.Socket;

/**

  • @author 高圆圆

  • @date 2022/11/28 14:57 */

    public class Tcp_ServerTest2 {
    public static void main(String[] args) throws IOException {
        //创建服务器端的Socket对象
        ServerSocket ss = new ServerSocket(2222) ;
        //监听客户端连接
        Socket s = ss.accept();
        //获取监听客户端所在的通道内字节输入流对象---->包装成字符缓冲输入流
        BufferedReader br = new BufferedReader(
                new InputStreamReader(s.getInputStream())) ;

    //将监听客户端的通道内的字节流(已经被包装了字符缓冲输入流)的内容----通过的字符缓冲输出流写入到文件中
    BufferedWriter bw = new BufferedWriter(
            new FileWriter("D:\\EE_2211\\day27_code_resource\\copy.java")) ;
    //一次读取一行,写一行到文件中
    String line = null ;
    while((line=br.readLine())!=null){//阻塞式,null也是表示客户端的通道内的字节输入流读完了
    ​
      /*  if("over".equals(line)){
            break;
        }*/
        bw.write(line);
        bw.newLine();
        bw.flush();
    }
    ​
    //加入反馈,服务器端反馈给客户端数据
    //获取字节输出流,写
    OutputStream out = s.getOutputStream();
    out.write("hello,文件复制完毕".getBytes());
    out.flush();
    ​
    //释放资源
    bw.close();
    ss.close();
    }}

客户端

import java.io.*; import java.net.Socket;

  • 发现问题:

  • 两个端都出现了互相等待了

  • 因为客户端的文本文件读完,是null作为结束条件,但是服务器端不断的从通道内的输入流去读数据,

  • 两端的通道不知道文件是否完了(服务器端不知道客户端的文件完没完),等待着写数据过来,

  • 解决方案:

  • 通知服务器端,别等了,文件读完了

  • 1)自定义结束条件 ,服务器端读到自定义结束条件,就反馈!

  • 弊端:如果文件第一句话恰好是自定义的结束条件,就不好

  • 2)推荐:在客户端这边有个终止通道内的流 没有数据写过去了!禁止输出流输出!

  • public void shutdownOutput() throws IOException

    public class Tcp_ClientTest2 {
    public static void main(String[] args) throws IOException {
        //创建客户端的Socket对象
        Socket s = new Socket("10.35.162.121",2222) ;
        //创建字符缓冲输入流对象
        BufferedReader br = new BufferedReader(
                new FileReader("UdpReceive.java")) ;
    //获取客户端通道的字节输出流---->包装成BufferedWriter:字符缓冲输出流
    BufferedWriter bw = new BufferedWriter(
            new OutputStreamWriter(s.getOutputStream())) ;
    ​
    //每次从.java文件读取一行,给通道流的流中写一行
    String line = null ;
    while((line=br.readLine())!=null){//阻塞式方法.一直等待为null文件完毕
        bw.write(line) ;
        bw.newLine();
        bw.flush();
    }
    ​
    //写一个数据
    //通道内的流写一句

    /* bw.write("over"); bw.newLine(); bw.flush();*/

    //方案2: public void shutdownOutput()   throws IOException
    s.shutdownOutput();
    //客户端要读取服务器反馈数据
    //获取通道内的字节输入流
    InputStream inputStream = s.getInputStream();
    //读取一个字节数组
    byte[] bytes = new byte[1024] ;
    int len = inputStream.read(bytes);
    System.out.println("客户端接收到了反馈数据:"+new String(bytes,0,len));
    //释放资源
    br.close();
    s.close();
}

}

5.反射(前期了解,二阶段学习Servlet服务器端程序开发,都是反射)

咱们之前写代码:类名 对象名 =  new 类名() ;考虑运行阶段 Runtime
​
反射里面研究的类的编译阶段:  Class---->编译的过程
1.反射中如何获取类字节码文件对象
2.反射中是如何通过构造器创建对象呢?
3.通过反射创建对象之后,在去给成员变量赋值
4.通过反射创建对象之后,调用类的成员方法..

'什么是反射?

  • 编译某个类的时候---->获取这个类的字节码文件,然后去加载,调用里面的成员方法,访问成员变量,

  • 通过构造方法创建对象! *

  • 编译过程:

  • 对这个类的属性/成员/构造其进行校验---->类加载器(负责类的加载过程)

  • BoostrapClassLoader:启动类加载器,负责java核心库,rt.jar *

  • 如何获取一个类的字节码文件?

  • java.lang.Class:代表正在运行的java类或者接口,通过静态方法

  • public static Class forName(String classname):

  • 参数:代表就是当前类或者接口的全限定名称 (包名.类名)

  • String---->全限定名称 java.lang.String

  • Person---->自定义的---->全限定名称:com.qf.reflect_06.Person

2.通过反射方式获取类的字节码文件之后,创建当前类对象!

  • 之前的写法:考虑运行的代码 类名 对象名 = new 类名() ;

  • 1)获取类的字节码文件对象

  • 2)获取类的Constructor所在的构造器对象

  • 3)通过它创建当前类实例

2)获取指定的构造方法所在的Constructor类对象** //public Constructor<T> getConstructor(Class<?>... parameterTypes) //获取指定的公共的构造方法所在Constructor实例,参数--->参数类型的Class字节码文件对象 //参数是String----->String.class----结果 java.lang.String**

3)通过它创建当前类实例** //public T newInstance(Object... initargs):参数就给构造函数中参数进行实际赋值

2)获取构造器Constructor类对象--->带两个参数的

//public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) ​ //参数里面是参数类型的字节码文件对象

AccessibleObject类提供Field(成员变量的类对象)/Method(成员方法类对象)/Constructor(构造器类对象)的基类 //提供功能:取消Java语言访问检查,暴力访问 //public void setAccessible(boolean flag) true:就是抑制Java语言访问检查功能

public class ReflectDemo2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取当前类字节码文件
        Class clazz=Class.forName("Reflect.Person");
        //创建对象,获取当前类的构造函数
        Constructor con=clazz.getConstructor();
        //创建对象,获取当前类的有参构造器
        Constructor con1=clazz.getDeclaredConstructor(String.class,int.class);
        System.out.println(con);
        con1.setAccessible(true);
        Object obj=con.newInstance("达达利亚",20);
        System.out.println(obj);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第一开始学习Vue 3,首先要了解Vue的基本概念和核心功能。Vue是一个用于构建用户界面的渐进式JavaScript框架,它采用组件化的方式来开发应用程序。 在Vue 3中,有一些重要的变化和改进。首先,Vue 3引入了Composition API,这是一个全新的API,可以让我们更好地组织和共享组件逻辑。通过Composition API,我们可以使用函数来编写组件的逻辑,而不仅仅是通过选项对象。 另一个重要的改进是性能的提升。Vue 3在内部进行了许多优化,例如使用Proxy替换了原来的Object.defineProperty来实现响应式系统。这使得Vue 3在处理大型数据集和性能敏感应用程序时更高效。 还有一项重大的变化是对TypeScript的更好支持。Vue 3引入了许多类型声明文件,使得在使用TypeScript时更容易推断和检测组件的类型。 在第一,我们可以开始学习Vue 3的安装和使用。我们可以通过npm或yarn来安装Vue,然后使用Vue的命令行工具创建一个新的Vue项目。 接下来,我们可以学习Vue的基本语法和核心概念,例如如何定义一个组件、使用指令和插值表达式、处理事件等。 最后,我们可以尝试编写一个简单的Vue应用程序,并将其运行起来。通过实践,我们可以更加深入地理解Vue的使用和原理。 第一是学习Vue 3的基础,为接下来的学习打下坚实的基础。希望通过努力学习,在接下来的30内可以精通Vue 3的使用和开发。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值