第五周笔记

一、Map集合

1.Map集合的基本功能

V put(K key,V value) :添加方法---返回值什么意思?
                   通过返回值是否为null,判断键是否重复,如果不重复,返回值永远是null;
                   如果键重复,将第一次存储键对应的值返回,将后面键对应的值进行存储
   void clear():清空Map集合的所有键值对
   V remove(Object key):删除Map集合的指定键,然后返回被删除的值
   boolean containsKey(Object key):是否包含指定的键
   boolean containsValue(Object value):是否包含指定的值
   boolean isEmpty():判断Map集合是否为空

2.Map集合的遍历方式

//Map集合遍历方式:
  //1)Set<K> keySet()获取Map集合的所有的键的集合
   //       V get(Object key):通过键获取值
       Map<String,String> map = new HashMap<>();
       Set<String> key = map.keySet();
       for(String s : key){
       String value = map.get(s);
       System.out.println(s+value)
       }
 // 2)Set<Map.Entry<K,V>> entrySet() 获取所有键值对对象
     //   K getKey()获取键
      //  V getValue()
	   Map<String,String> map = new HashMap<>();
	   Set<Map.Entry<String,String> en = map.entrySet();
	   for(Map.Entry<String , String> e : en){
           String key = e.getKey();
           String value = e.getValue()
       }

3.HashMap集合

HashMap--->底层哈希表实现,put方法依赖hashCode和equals方法,
Map针对键有效,要针对键的类型自定类型,当前类必须重写equals和hashCode(),保证键唯一(重点)

4.TreeMap

TreeMap<K,V> 存储键值对元素,保证键唯一的同时,还有排序!
 使用哪种排序,取决于使用构造方法:
      public TreeMap():自然排序,当前键的类型必须实现Compareable接口
      public TreeMap(Comparator<? super K> comparator):使用比较器排序 (推荐) 直接可以使用接口匿名内部类

5.Collections工具类

java.util.Collections:针对集合操作工具类
提供一些常用的方法:
    public static <T> int binarySearch(List<? extends Comparable<? super T>> list,T key):
    二分搜索在List中查询元素 (不管集合还是Arrays---->binaraySearch方法,(集合或者数组必须有序))
    public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) :获取Colection中的最大值
    
    public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll) :获取Colection中的最小值
    public static <T extends Comparable<? super T>> void sort(List<T> list):针对List集合进行自然排序
    	实现的接口是一个自然排序Compareable
    public static <T> void sort(List<T> list,Comparator<? super T> c):针对List集合比较器排序
    	Collections.sort(list , new Comparator<>(
    		public int compare(Object o1,Object o2){
    			return 0;
    		}
    	))
    public static void shuffle(List<?> list):针对List集合随机置换

    public static <T> List<T> synchronizedList(List<T> list):将线程不安全ArrayList,变成线程安全的列表
Map集合和Collection集合的区别?
        1)存储类型
            Collection<E>,只能存储一种引用类型---属于"单列集合"---->理解为"光棍"
            Map<K,V>,可以存储多种类型的引用类型--->属于"双列集合"----理解为"夫妻对"
        2)关系区别
            Collection和Map没有直接关系,间接关系
                Collection具体的子接口Set--->HashSet/Treeset 直接的去依赖于Map接口的HashMap和TreeMap


        

二、异常

1.什么是异常

程序中会出现异常,开发人员必须解决异常!
异常的父类:Throwable
         -->提供一些方法:将异常的信息直接打印在控制上:具体(跟踪堆栈-->底层原码)
         public void printStackTrace()
     Error(严重问题)     Exception
 严重问题:内存溢出(借助于其他硬件解决这个问题,加内存条)
 Exception:
       编译时期异常:只要不是RuntimeException的子类,都属于编译时期
                   必须让开发人员必须处理,不处理,代码编译通过不了!
       运行时期异常:RuntimeException
              大部分逻辑不够严谨,导致出现的问题
              NullPointerEception:在获取到某个类的对象的时候,并没有非空判断,
                      可能对象是null,使用这个对象调用它里面的方法,出现空指针了

2.异常的格式

	 throws:抛出
     //标准格式
     try{
         可能出现问题的代码
     }catch(异常类名 对象名){
         处理异常
     }finally{
         //释放资源
     }

     变形格式
     try{
         可能出现问题的代码
     }catch(异常类名 对象名){
         处理异常
     }


     try{
           可能出现问题的代码
       }catch(异常类名 对象名){
           处理异常
       }catch(异常类名2 对象名2){
         处理异常..
     }

3.throw和throws的区别

异常处理
  throws:抛出
  throw:抛出

  区别:
	1)书写位置的区别
	    throws:用在方法声明上
	    throw:用在方法体中
	2)后面跟的类型不一样的
	    throws后面跟的异常类名,可以多个,中间逗号隔开
	    throw:后面只能一个异常对象,new XXException()
	3)是否出现异常的时机
	        throws:可能出现问题,可能性
	        throw:执行某个逻辑代码,一定会出现这个异常!(肯定性)
4)处理异常:
  throws:抛出给调用者,谁调用这个方法(带有throws的方法),谁必须对这个已处理(throws/try...catch...)
  throw:异常的处理:交给方法体中逻辑判断,if(xxx){throw  new XXException(...);}

4.异常的注意事项

异常的使用的注意事项:
   1)子类继承父类的时候,如果子类重写父类的方法,父类的方法如果本身没有throws抛出异常
   	   子类的方法中出现异常,子类只能自己处理,只能try...catch...

   2)子类继承父类,子类重写父类方法的时候,如果父类的方法抛出异常,
       那么子类的该方法最起码要根父类的方法异常保存一致(要么子类存放的异常是父类方法的异常中的子类)

三、线程

1.线程和进程的概念

线程是依赖于进程的,没有进程就没有线程!
进程
    在计算机的任务管理查看到此电脑上所有的客户端的进行!
    概念:
        调用"系统资源"的独立单位!
        开启一个进程----创建 "系统资源"
所有的计算机,包括我们"jvm",都支持多进程,多进程的意义?
    一句话:提高CPU的使用率!
    在打游戏的同时,听音乐,---同时开启了两个进程,是同时进行的吗?
    并不是同时的,CPU(时间片),一点点时间片可以高效在两个进制来回切换!

线程:
    是进程中的最小执行单元!(理解为,进程中的某个任务)
    举例:
            360进程开启之后,可以杀毒/清理/电脑瘦身等等
    多线程:在一个程序的过程中,其执行路径有多条,线程的执行具有"随机性"!
    多线程的意义?
            多个线程"共享同一个资源",互相抢占CPU执行权,从而达到线程的执行速度!

            举例
                1 v 3 打篮球,3个人抢占的篮球的几率大,可能这1个人也能抢占大篮球!

2.创建线程的两种方式

1).通过继承Thread 创建

/**
	1)自定义一个类 继承Thread类
    2)重写Thread类的run方法
    3)在main()用户线程中,创建当前线程了对象
    4)启动线程--->start()不是run方法,run方法是一个普通方法
    Thread类提供方法:
              public final String getName()获取线程的名称
              public final void setName(String name):设置线程名称
    */
	class X extends Thread{
		public void run(){
			//耗时的操作;
            //获取线程的名字:getName()
		}
	}
	public static void main(String[] args){
		X x = new X();
		x.start();
	}

2)通过实现Runnable接口创建

/**
	线程的创建方式2:
   1)自定义一个类,实现Runnable接口
   2)重写Runnable接口的run方法
   3)在用户线程main中去创建当前类对象--->"资源类"
   4)创建Thread类对象,将3)资源类作为Thread类对象的参数进行传递
*/
class X implements Runnable{
    public void run(){
        //耗时的操作
        //获取线程名字:Thread.currThread().getName()
    }
}
public static void main(String[] args){
		X x = new X();
    	Thread td = new Thread(x,"线程1");
    	td.start();
	}

3.线程的方法

1)join等待该线程中终止

	public final void join() throws InterruptedException
因为线程的执行具有随机性,哪个线程启动之后,调用join(),正常理想情况,等待该线程执行完毕,执行其他线程!

2) yield线程礼让

	public static void yield():线程礼让(暂停当前正在执行的线程,执行其他线程)

4.线程的优先级

public final void setPriority(int newPriority):设置优先级
public final int getPriority():获取优先级

 Thread提供三个自定义常量:
     public static final int MAX_PRIORITY    10    最大优先级
     public static final int MIN_PRIORITY    1    最小优先级
     public static final int NORM_PRIORITY   5    默认优先级
 创建线程,没有设置优先级,线程的默认优先级就是5(抢占CPU执行权的概率一样大)

5.同步方法

/**什么是同步方法?
	如果一个成员方法中进来就是一个synchronized(锁对象){}--同步代码块,将synchronized提到方法声明上
	默认的锁对象this

	如果是静态的同步方法,锁对象是 "当前类名.class"--跟"反射"有关系
            反射:Java代码经历三个阶段
                    "SORUCE"  ,"CLASS"(反射中的核心)  "RUNTIME"*/
public class Abc implements Runnable{
	void run(){
		if(){
			//sysnchronized(this){//当前类对象的地址引用
            sysnchronized(Abc.class){//当前类对象的字节码文件对象
				//.....
			}
		}else{
			cell();
		}
	}
	//class synchronized void cell(){//
    class static synchronized void cell(){
		if(){
     		//....       
        }
	}
}

6.死锁

1)死锁

	两个或者两个以上的线程,在执行的过程中,互相持有对方的锁,需要等待对方释放锁,导致出现了互相等待情况!

             举例:
                     中国人和美国人吃饭
                     一双筷子 / 一把刀/一把叉

                     中国人:
                             一根筷子/一把刀
                      美国人:
                             一跟筷子/一把叉
    解决死锁:多个线程必须使用统一资源对象!  (引入生产者和消费者模式思想)

2)wait()和notify()

属于Object类中:	
	wait() 等待,当调用这个方法时,会立即释放锁
	notify() 唤醒线程

3)解决死锁的办法–生产者/消费者模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dn1JAAZU-1679816832552)(E:\后端\笔记\第一阶段\生产者消费者.png)]

使用生产者和消费者模式思想,来解决线程死锁问题!
    组成:
            Student类:姓名,年龄两个学数据
            SetTread类:生产资源类,里面产生学生数据
            GetThred类:消费者资源类,里面使用学生数据
            ThreadDemo类:用户线程,等会开启两个生产者所在的线程/消费者所在的线程
   问题1:
        输出null--0,因为生产资源类中和消费资源类中并没有使用同一个资源!
   优化:
        需要不断的在生产资源类中产生学生数据,在消费者资源类中不断地使用学生数据!
   问题2:
        不断的在生产者资源类中产生数据,消费者资源不断使用使用数据,出现数据紊乱!
                姓名和年龄不符! ---多线程环境不安全
        ---需要多线程安全问题

        校验多线程安全问题的标准:
                1)是否是多线程环境
                2)是否存在共享数据
                3)是否有多条语句对共享数据操作
                使用同步代码块---将3) 包起来

   问题3: 加入同步代码块,解决了线程安全问题,数据不会紊乱,但是数据一打印一大片
    原因:线程的执行,通过cpu一点点时间片,足够线程执行很多次!



  最终版本:
        想依次打印数据:------->Java中的等待唤醒机制
        生产者不断产生数据,当他没有数据了,等待产生数据之后,通知(唤醒)消费者所在的线程来使用数据!
        消费者不断使用数据,当他有数据了,等待先使用数据,使用完毕没有数据了,通知(唤醒)生产者所在的线程来产生数据!

       (多线程 "信号灯法")
                   你一次
                   我一次

       wait()+notify() 也算Java同步机制         必须使用使用锁对象调用方法

7.jdk5以后锁定操作

jdk5以后提供了具体的"锁定操作"
java.util.concurrent.locks.Lock接口---->可重入的互斥锁ReentrantLock
	具体锁
		Lock lock = new ReentrantLock()
 提供一些方法,可以获取锁,可以去释放锁
         void lock() 获取锁
         void unlock()释放锁

8.问题

面试题:
      1)jvm是多线程的吗?
          是多线程;至少有两条件线程
          1)main---"用户线程"
          2)垃圾回收线程,回收没有更多的引用对象,从而释放空间;如果没有
      垃圾回收线程,Java中不断的去new,不断的堆内存空间---->导致OOM(Out Of Memory:内存溢出)

     2)Java能创建线程吗?
	创建线程--->创建进程---->创建系统资源---->Java不能够直接创建资源的,间接的提供了一个Thread      

四、线程池–Executors

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5KaTgfut-1679816832554)(E:\后端\笔记\第一阶段\线程池原理.png)]

1.线程池

线程池:
     可以通过Executors工厂类(当前类构造方法私有化,对外提供静态方法--->简单工厂模式)提供一些创建线程池的功能
可以创建固定的可重用的线程数的线程池
     public static ExecutorService newFixedThreadPool(int nThreads):参数为当前的线程数量
     上面的返回值ExecutorService接口
           提供一些方法
             Future<?> submit(Runnable task)提交异步任务
             <T> Future<T> submit(Callable<T> task):提交异步任务
             void shutdown():关闭线程池
 创建线程池
 	ExecutorService threadPool = Executors.newFixedThreadPool(2);
 提交异步任务
 	MyCallable myCallable = new MyCallable() ;
    threadPool.submit(myCallable) ;
    threadPool.submit(myCallable) ;
 关闭线程池
 	threadPool.shutdown();
 定义类
 public class MySelfCallable  implements Callable<Integer> {
        @Override
    public Integer call() throws Exception {
    	//需要的操作
        return sum;
    }
}

五、单例设计模式

单例设计模式---属于创建型设计模式(创建对象)
    概念:
            始终在内存中有且仅有一个当期类的实例!(有一个对象)

1.两种设计模式

单例设计模式:
      1)饿汉式

      2)懒汉式

  饿汉式:不会出现安全问题的单例设计模式
      1)当前类是具体类
      2)类一加载就创建当前类实例
      3)构造私有化,对外隐藏,不能new实例
      4)对外提供静态方法,返回值当前类本身

      Java中的类Runtime类:标准的单例(饿汉式),和计算机的运行环境有关系
/**单例设计模式之懒汉式(可能存在安全问题的一种单例模式)
    1)当前类是个具体类
    2)当前类构造方法私有化
    3)当前类的成员位置:声明当前类的一个静态变量
    4)对外提供静态方法,返回值是当前类本身:需要判断当前变量是否为null

    现实开发业务中:
        存在懒加载(按需加载)
        一个用户有多个账户: 一对多 (从用户维度去看账户) ,查询用户的时候,开启懒加载方式(针对用户用哪个账户查询哪个账户)
        账户的维度去看用户:一个账户从属于某个用户的  一对一*/
public class Teacher {
    //声明静态变量,t的类型Teacher
    private  static Teacher t ;
    //构造方法私有化:
    private Teacher(){}
    //对外提供静态方法,返回值是当期类本身
    //多个线程同时去访问这个方法,
    //线程1,线程2,线程3--导致出现线程安全问题
    public static synchronized Teacher getInstance(){//变成了静态的同步方法 :锁对象:类名.class
            if(t ==null){
                t = new Teacher() ;
            }
            return  t;
    }
}

六、IO流

1.File抽象路径形式

java.io.File--->表示文件或者文件夹(目录)一种抽象路径形式
构造方法:
	File(File parent, String child)从父抽象路径名和子路径名字符串创建新的 File实例。
	File(String pathname)通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
	File(String parent, String child)  父路径名字符串和子路径名字符串创建新的 File实例

1).File的基本功能以及特有功能

File的基本功能以及特有功能:
    public boolean createNewFile() throws IOException:创建文件
    public boolean mkdir():创建文件夹
    public boolean mkdirs():创建文件夹,当父目录不存在,自动创建
    public boolean delete():删除文件夹或则文件路径,如果是文件夹,必须是空目录
    public boolean exists():判断此路径名表示的文件或者目录是否存在
    public boolean isDirectory():此抽象路径名表示的文件是否是目录
    public boolean isFile():是否是文件
    public boolean isHidden():是否隐藏
    特有功能:高级功能
    public String[] list():获取指定抽象路径名表示的文件或者目录的名称(返回字符串数组)
    public File[] listFiles():获取指定路径名表示的文件或者目录的File数组

2).直接获取的同时就将满足条件的内容遍历

之前的写法:
     1)先获取当前指定路径形式下的所有的文件以及文件夹的File数组或者String[]数组
     2)然后在遍历
另一种方式:直接获取的同时就将满足条件的内容遍历
参数都是接口---FilenameFilter:文件名称过滤器
         public boolean accept(File dir,String name)
             将指定的文件存储在文件列表中dir,返回值true(存储在文件列表中),否则false,不存储
public File[] listFiles(FilenameFilter filter)
public String[] list(FilenameFilter filter)

2.字节流

1).字节输出流

	FileOutputStream 实现文件的字节数追加
	public FileOutputStream(String name,boolean append) throws FileNotFoundException
		第二个参数是true:自动追加内容
	IO流写数据,实现换行效果 widows系统 "\r\n"

2).字节输入流

InputStream:字节输入流--->抽象类--->具体的子类FileInputStream:文件字节输入流
	1)创建文件字节输入流对象FileInputStream(String name) :读取指定的文件 name:文件地址
	2)读数据
	   继承它父类的方法:public abstract int read()throws IOException:一次读取一个字节
	   		一次读取一个字节的方式:
				针对中文---会出现乱码 (char)字节数,平台默认编码格式utf-8:一个中文对应三个字节
				英文字母和中文-拼接一块,一个英文字母对应一个字节,这个时候拼接不上,导致文乱码---Java				   提供"字符流",解决乱码
	   public int read(byte[] b) throws IOException:一次读取一个字节数组
//最终代码:字节流一次读取一个字节数组
//创建一个字节缓冲区:长度:1024或者1024整数倍
byte[] bytes = new byte[1024] ;
//实际字节数从0开始
int len = 0 ;
while((len=fis2.read(bytes))!=-1){//赋值,判断-- read(byte[] bytes):阻塞式方法,没有到-1,就一直读
	String str = new String(bytes,0,len) ;
	System.out.println(str);
}

3)字节缓冲流

Java之IO流提供了字节缓冲流:让读取的速度更快一些,提供对应的类
	字节缓冲输入流/字节缓冲输出流  (高效的字节流)---仅仅是内部提供缓冲区字节数组长度:8192长度,
	     文件的读写复制还的依赖于基本字节流(InputStream/OutputStream)
	BufferedInputStream(InputStream in):字节缓冲输入流
	BufferedOutputStream(OutputStream out):字节缓冲输出流
推荐"使用字节缓冲流"完成图片文件/视频文件/音频文件的读取!

3.字符流

1)字符输入流

字符输入流---->Reader(抽象类)--->
	具体的子类:字符转换输入流InputStreamReader --- 将字节输入流---->转换--->字符输入流
	public InputStreamReader(InputStream in):使用平台默认字符集进行解码---读取数据
	public InputStreamReader(InputStream in,String charsetName)
	            使用指定字符集解码---读取数据
	
	 读数据:
	    int read() :一次读取一个字符  --->返回结果:实际的字符数
	    int read(char[] cbuf) :一次读取一个字符数组
	    int read(char[] cbuf,int off, int len):读取字符数组的一部分

2)字符输出流

字符输出流:Writer(抽象类)--->
   具体的子类 OutputStreamWriter:字符转换输出流,"可以将字节输出流---转换---字符输出流"
   构造方法:
        public OutputStreamWriter(OutputStream out):使用平台默认字符集进行编码--输出数据
        public OutputStreamWriter(OutputStream out,String charsetName):
                           使用指定的字符集进行编码---输出数据
   写数据:
         void write(char[] cbuf) :写入字符数组
         void write(char[] cbuf,int off,int len ) :写入字符数组的一部分
         void write(int c) :写一个字符
         void write(String str) :字符串
         void write(String str,int off,int len):写入字符串的一部分

3)字符缓冲流

BufferedReader:字符缓冲输入流---可以读取一行内容
构造方法:
 public BufferedReader(Reader in):提供默认缓冲区大小的字符缓冲输入流 (8192个长度)
             这个流如果直接操作文件--->参数里面使用FileReader
     特有功能:
         public String readLine()throws IOException:一次读取一行
                     返回值是读取到这一行的内容,当流已经到达末尾,则返回null
BufferedReader br = new BufferedReader(new FileReader("copy.java")) ;
键盘录入
   	1)Scanner(InputStream in)---->Scanner sc = new Scanner(System.in) ;
   	2)new BufferedReader(new InputStreamReader(System.in))
                                --->InputStreamReader(InputStream in)
    //键盘录入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
字符缓冲输出流:提供字符数组/字符/字符串的一种高效写入
BufferedWriter构造方法
    public BufferedWriter(Writer out):提供默认缓冲区大小的字符缓冲输出流,默认缓冲区足够大 8192长度
	写的功能:
	    write(字符/字符数组/字符串...)
	    特有功能:
	       不需要在使用"\r\n"换行符号, public void newLine()写入行的分隔符
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt",true)) ;

七、属性集合列表

java.util.Properties:属性集合列表---extends Hashtabl<K,V>-->

         本质是Map<K,V>集合
         添加功能:put(K key,V value)
         遍历方式:Set<K> keySet()
                 遍历键-->通过键获取值 V get(K key)

自己的特有功能:
     java.util.Properties:没有泛型,键和值都只能String---->
                 作用:用来读取配置文件xx .properties配置文件(src下面)
     构造方法:
             public Properties()
     添加属性列表的键和值:
             public Object setProperty(String key,String value)
     特有的遍历方式:
             public Set<String> stringPropertyNames():获取属性列表中的所有的键(属性名称)
             public String getProperty(String key):通过属性列表中的属性名称获取对应的值
将文件的内容加载到属性集合列表中:
	public void load(InputStream inStream/Reader)
	将属性列表中的内容保存到指定文件中
	第二个参数:描述属性列表
	prop.store(new FileWriter("D:\\EE_2302\\day27\\code\\day27\\src\\my.properties"),"name'list") ;
读取到src下面配置文件的内容--->存储到字节输入流中	
	public void store(OutputStream out/Writer,String comments)
	InputStream inputStream = PropertiesDemo2.class.getClassLoader().
                getResourceAsStream("name.properties");
    prop.load(inputStream);

七.递归

方法递归:
   方法本身调用方法的一种现象
   前提条件:
     1)定义一个方法
     2)这个方法的逻辑是规律的
     3)这个方法是有结束条件,否则---成了"死递归"

八、网络编程

1.三要素

ip地址/端口号/协议
ip地址:
    A/B/C三大类
    A类--->前面第一个号段:网络号段  后面的号段:主机号段  (国家部门--机房)
    B类--->前面两个号段:网络号段  后面号段:主机号段 (大学校园/公司内网等等)
    C类---->属于私人地址 前面三个号段:网络号段  后面号段:主机号段
             10.35.165.17   --- "点分十进法"
端口号:
    范围 0~65535 这里面 0-1024(属于保留端口号)
    自己指定端口号--->1025-65535
    (不要和系统端口号冲突---->Address already in use:BindException:地址被占用)
协议:
    UDP/TCP协议区别  (底层网络协议)
    UDP协议:
        1)属于不可靠连接,不需要建立连接通道(不安全)  ----以"数据报包"的方式进行数据传输的
        2)不同步的,执行效率相对TCP协议,效率高
        3)发送数据大小有限制的!

    TCP协议:
        1)属于可靠连接,需要建立连接通道!   ----以 "流"的方式发送数据
        2)同步的,执行效率低,安全性相对UDP协议(安全性能高)
        3)发送数据大小无限制!    

2.InterAddress

java.net.InetAddress:代表互联网ip地址对象!
	获取ip地址对象---->获取ip地址字符串形式/获取主机名称
	参数:要么传入主机名称/要么ip地址字符串
	public static InetAddress getByName(String host)throws UnknownHostException :获取互联ip地址对象
	InetAddress的成员方法
	public String getHostAddress():获取ip地址字符串形式
	public String getHostName():获取ip地址的主机名

3.UDP发送端

java.net.DatagramSocket:此类表示用于发送和接收数据报数据包的套接字
public DatagramPacket(byte[] buf,int length,InetAddress address,int port)
	创建"数据报包"--里面包括:数据内容,ip地址,端口号
       java.net DatagramPacket
       参数1:分组数据(字节数组)
       参数2:包的长度
       参数3:ip地址对象
       参数4:端口号
使用发送端的Socket对象发送"数据报包"
       public void send(DatagramPacket p)throws IOException从此套接字发送数据报包

4.UDP接收

使用UDP协议发送数据
	1)创建发送端的socket对象
	2)创建"数据报包"--里面包括:数据内容,ip地址,端口号
	3)使用发送端的Socket对象发送"数据报包"
	4)释放资源
创建接收端的Socket对象
    public DatagramSocket(int port)throws SocketException
创建一个"数据报包"在里面自定义缓冲区:将发送端是数据存储到缓冲区中(字节数组,长度:1024或者1024的整数倍)
	public DatagramPacket(byte[] buf,int length)
    	参数1:用于保存传入"数据报"的缓冲区。
    	参数2:要读取的字节数
public void receive(DatagramPacket p)throws IOException从此套接字接收数据报包  
public byte[] getData() :解析数据报包中DatagramPacket
public int getLength():解析数据报包中DatagramPacket中的实际字节数组长度
谁发送的数据---获取ip地址字符串形式
    数据报包DatagramPacket--->public InetAddress getAddress()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值