代码改变世界

udp和tcp

2018-06-30 18:28  yelena  阅读(149)  评论(0编辑  收藏  举报

网络通信协议

tcp/ip协议:包括TCP协议和IP协议,UDP协议和其它一些协议的协议组

层次结构:应用层---传输层---网络层---链路层

ip地址:唯一标识一台计算机  

ipv4版本:4个字节的二进制数表示(一共4个字节,一个字节有8位,用0和1表示),转换成十进制后就是常见的形式,127.0.0.1

端口:通过ip地址找到 计算机,然后通过端口号来找到指定的应用程序

inetaddress类:封装一个ip地址,包含主机名

构造方法

getbyname():静态方法,需要传一个字符串表示的ip地址,返回一个inetaddress对象

getlocalhost():静态方法,空参,返回本地主机的inetaddress对象

方法

gethostname():空参,返回表示此ip地址的主机名的字符串

gethostaddress():空参,返回表示ip地址的字符串

InetAddress inet = InetAddress.getLocalHost();
        //System.out.println(inet);
//        String[] str = inet.toString().split("/");
//        for(String s:str){
//            System.out.println(s);
//        }
        //System.out.println(inet.getHostName());
        //System.out.println(inet.getHostAddress());
        InetAddress inet1 = InetAddress.getByName("123-pc");
        System.out.println(inet1);

udp协议:无连接通信协议,数据传输时,数据的发送端和接收端不建立逻辑连接

占用资源小,通信效率高,视频、音频和普通数据的传输,丢包不会对结果产生太多影响

传输重要数据不适用udp

数据大小被限制在64k以内

tcp协议:面向连接的通信协议,传输数据前先在发送端和接收端建立逻辑连接,然后再传输数据,提供了两台计算机之间可靠无差错的数据传输

面向连接的特效,保证了数据传输的安全性(完整性),下载文件时采用tcp协议

udp的使用

datagrampocket类:用来打包用户的数据,相当于集装箱

getaddress():返回一个inetaddress对象

getport():返回端口号

getlength():用来获取数据的大小

datagramsocket类:用来传输集装箱,相当于码头

send():发送数据

receive():接收数据

发送端:使用datagrampocket类四个参数的构造方法;使用datagramsocket类的空参构造(不需要指定端口号,系统自动分配一个没被占用的端口号)

接收端:使用datagrampocket类两个参数的构造方法;使用datagramsocket类的有参构造(指定端口号,可以监听指定的端口号)

byte[] bytes = "你好".getBytes();
        InetAddress inet = InetAddress.getLocalHost();
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length, inet, 8000);
        DatagramSocket ds = new DatagramSocket();
        ds.send(dp);
        ds.close();
DatagramSocket ds = new DatagramSocket(8000);
        byte[] bytes = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
        ds.receive(dp);
        int len = dp.getLength();
        String ip = dp.getAddress().getHostAddress();
        int port = dp.getPort();
        System.out.println(ip+"..."+port+"..."+new String(bytes,0,len));
        ds.close();

 tcp的使用

客户端:scocket

构造方法:有参构造,传入一个表示服务器端ip地址的字符串和端口号

方法:getinputstream()获得输入流;getoutputstream()获得输出流

不需要自己去创建流,用方法调用

服务器端:serversocket

构造方法:有参构造,传入端口号

方法:accept()获得一个socket对象,调用其方法

Socket socket = new Socket("127.0.0.1", 8888);
        OutputStream out = socket.getOutputStream();
        FileInputStream fis = new FileInputStream("d:\\12\\123.jpg");
        int len =0;
        byte[] bytes = new byte[1024];
        while((len=fis.read(bytes))!=-1){
            out.write(bytes, 0, len);
        }
        socket.shutdownOutput();
        InputStream in = socket.getInputStream();
        len = in.read(bytes);
        System.out.println(new String(bytes,0,len));
        fis.close();
        socket.close();
ServerSocket server = new ServerSocket(8888);
        Socket socket = server.accept();
        InputStream in = socket.getInputStream();
        File upload = new File("d:\\12\\upload");
        if(!upload.exists()){
            upload.mkdirs();
        }
        String filename = "oracle"+System.currentTimeMillis()+new Random().nextInt(9999)+".png";
        FileOutputStream fos = new FileOutputStream(upload+File.separator+filename);
        byte[] bytes = new byte[1024];
        int len =0;
        while((len=in.read(bytes))!=-1){
            fos.write(bytes, 0, len);
        }
        OutputStream out = socket.getOutputStream();
        out.write("上传成功".getBytes());
        fos.close();
        socket.close();
        server.close();

服务器端多线程:

public class Upload implements Runnable {
    private Socket socket;
    private FileOutputStream fos;
    public Upload(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        try{
        InputStream in = socket.getInputStream();
        File upload = new File("d:\\12\\upload");
        if(!upload.exists()){
            upload.mkdirs();
        }
        String filename = "oracle"+System.currentTimeMillis()+new Random().nextInt(9999)+".png";
        fos = new FileOutputStream(upload+File.separator+filename);
        byte[] bytes = new byte[1024];
        int len =0;
        while((len=in.read(bytes))!=-1){
            fos.write(bytes, 0, len);
        }
        OutputStream out = socket.getOutputStream();
        out.write("上传成功".getBytes());
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            try {
                fos.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                socket.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}
ServerSocket server = new ServerSocket(8888);
        while (true) {
            Socket socket = server.accept();
            Upload upload = new Upload(socket);
            Thread thread = new Thread(upload);
            thread.start();
        }

类加载

类未被加载到内存中,系统通过加载,连接,初始化三步对此类进行初始化

加载:把class文件加载到内存中,并生成一个class文件

连接:1、验证,验证类的内部结构,并与其它类协调;2、准备,为静态成员分配内存,并赋值;3、解析,将二进制的符号引用变成直接引用

初始化:学过的

类初始化时机:1、创建类的对象;2、给静态成员变量赋值;3、使用静态方法;4、反射;5、初始化某个类的对象;6、直接java.exe来运行某个类

类的加载器:根类加载器   扩展类加载器   系统类加载器

反射

在java中,动态获取信息及动态调用对象方法的功能叫做反射机制

class类

构造方法:没有,只能通过方法获得对象

1、某类的对象调用getclass()方法

2、类名直接调用class静态成员变量

3、class.forname(),传入一个字符串,可以和properties文件一起使用

Person p = new Person();
       // Class c = p.getClass();
      //  System.out.println(c);
      //  Class c1 = Person.class;
  //      System.out.println(c1);
//        System.out.println(c==c1);
//        System.out.println(c.equals(c1));
//        Class c2 = Class.forName("com.oracle.demo02.Person");
//        System.out.println(c2);

方法:

constructor:表示构造方法

field:表示成员变量

method:表示成员方法

declared:可以获得私有和公有的所有方法

setAccessible():允许对私有化的成员进行修改,暴力反射中的

constructor中的newinstance()方法,返回的是一个obj类型的对象,如果需要使用本类的方法,需要强转

//反射获取空参构造
        Class c = Class.forName("com.oracle.demo02.Person");
        //获取所有的公共构造方法
//        Constructor[] con = c.getConstructors();
//        for(Constructor c1:con){
//            System.out.println(c1);
//        }
        Constructor con = c.getConstructor();
        //Object obj = con.newInstance();
        Person p = (Person)con.newInstance();
        p.work("zhangsan");
        //System.out.println(obj);
//获取有参构造
        Class c = Class.forName("com.oracle.demo02.Person");
        Constructor con = c.getConstructor(String.class,int.class);
        System.out.println(con);
        Object obj = con.newInstance("zhangsan",18);
        System.out.println(obj);
//快速获取空参构造方法并创建对象
//        Class c = Class.forName("com.oracle.demo02.Person");
//        Object obj = c.newInstance();
//        System.out.println(obj);
        //获取私有的构造方法
        //暴力反射,破坏了程序的封装性和安全性
        Class c = Class.forName("com.oracle.demo02.Person");
//        Constructor[] con = c.getDeclaredConstructors();
//        for(Constructor cc:con){
//            System.out.println(cc);
//        }
        Constructor con = c.getDeclaredConstructor(int.class,String.class);
        //System.out.println(con);
        con.setAccessible(true);
        Object obj = con.newInstance(18,"zhangsan");
        System.out.println(obj);
    }
//通过反射获取成员变量并改值
        Class c = Class.forName("com.oracle.demo02.Person");
        Object obj = c.newInstance();
//        Field[] fields = c.getFields();
//        for(Field f:fields){
//            System.out.println(f);
//        }
        Field field = c.getField("name");
        Field field1 = c.getDeclaredField("age");
        //System.out.println(field);
        field.set(obj, "zhangsan");
        field1.setAccessible(true);
        field1.set(obj, 25);
        System.out.println(obj);
    }
//获取所有公共的方法,包括继承来的
//        Method[] m = c.getMethods();
//        for(Method mm:m){
//            System.out.println(mm);
//        }
        Method method = c.getMethod("eat");
        System.out.println(method);
        method.invoke(c.newInstance());
//获取有参方法并运行
        Class c = Class.forName("com.oracle.demo02.Person");
        Method method = c.getMethod("work", String.class);
        method.invoke(c.newInstance(), "zhangsan");

泛型擦除

有泛型的类,在程序进行编译后生成的class文件中,没有泛型约束,这叫做泛型擦除

//有一个ArrayList<String> list
        //然后往里面添加int类型数据
        //泛型擦除,字节码文件中没有泛型
        ArrayList<String> arr = new ArrayList<String>();
        arr.add("abc");
        Class c = arr.getClass();
        Method addd = c.getMethod("add", Object.class);
        addd.invoke(arr, 1);
        for(Object o:arr){
            System.out.println(o);
        }

反射配置文件

//类不清楚,方法也不清楚
        //通过配置文件去实现,运行类名和方法名已键值对的形式
        //保存到properties中,具体运行哪个类里面的方法通过改配置文件去设置
        //1.准备配置文件,写好键值对
        //2.IO读取配置文件reader
        //3.文件中的键值对存储到集合中,集合中保存的键值对就是类名和方法名
        //4.反射获取指定类的class文件对象
        //5.class文件对象获取指定方法
        //6.运行方法
        //Person p = new Person();
        //p.eat();
        FileReader fr = new FileReader("config.properties");
        Properties pro = new Properties();
        pro.load(fr);
        fr.close();
        String className = pro.getProperty("className");
        String methodName = pro.getProperty("method");
        Class c = Class.forName(className);
        Object obj = c.newInstance();
        Method method = c.getMethod(methodName);
        method.invoke(obj);