JAVA011【Socket网络编程】

DAY11

1.软件结构概述

  • ip 4 32为 分四组 8字
  • ip6 128 分八组 16字
  • 端口65535
  • 协议
package com.itheima._01软件结构概述;

/**
    目标:能够说出常见的软件结构及其优缺点

    讲解:
        1. 常见的软件结构


    小结:
        1. 常见的软件结构有:
            CS:客户端服务器结构
                优点:用户体验好,可以将一些运算交给客户端完成,减轻服务器端压力。
                缺点:开发成本高,维护成本高,开发周期长
            BS:浏览器服务器结构
                优点:只需要开发一个端,开发成本低,维护成本低,开发周期短。
                缺点:所有的运算都必须在服务器端完成,服务器压力大。用户体验差。
 */
public class Demo01 {
}
package com.itheima._01软件结构概述;

import java.io.File;

public class Demo {
    public static void main(String[] args) {
        File dir = new File("/Users/pkxing/Documents/119期就业班/课堂视频/day11");
        // 02-软件结构概述-[理解]-compress-20190813095735.mp4
        File[] files = dir.listFiles();
        for (File file : files) {
            String name = file.getName();
            if (name.contains("-compress")){
                int index = name.lastIndexOf(".");
                String ext = name.substring(index);
                String[] strs = name.split("-compress");
                File newName = new File(dir, strs[0] + ext);
                file.renameTo(newName);
            }
        }
    }
}

2.网络编程三要素

package com.itheima._02网络编程三要素;

/**
    目标:能够说出网络编程三要素的作用

    小结:
        网络编程三要素是什么:
            IP地址:网络设备的唯一标识
            端口号:进程的唯一标识
            通讯协议:确定数据的传输格式
                小结:通过IP找主机,通过端口找程序,通过协议确定如何传输数据。
 */
public class Demo02 {
}

3.UDP协议概述

  • 特点:UDP==》

    • User DatagramPacket Protocol 用户数据包协议
    • 面向无连接的协议
    • 只管发送,不确认对方是否能收到
    • 基本数据包进行数据传输:将数据,源以及目的地封装到数据包中
    • 数据包大小限制在64k以内
    • 因为面向无连接,速度快但不可靠(不安全)
  • UDP协议的应用场景

    • 即时通讯(QQ,陌陌…)
    • 在线网络视频
    • 网络电话
  • UDP协议相关的类

    • DatagramPacket:数据包对象:将数据,源以及目的地封装到数据包中 可以理解为:集装箱
    • DatagramSocket:发送或接收对象 码头
  • package com.itheima._03UDP协议概述;
    
    /**
        目标:理解UDP协议的特点(记忆)  面试题
    
        讲解:
            1. UDP协议的特点
                UDP ==> User DatagramPacket Protocol  用户数据包协议
                面向无连接协议
                只管发送,不确认对方是否能收到
                基于数据包进行数据传输:将数据,源以及目的地封装到数据包中
                数据包大小限制在64k以内
                因为面向无连接,速度快但不可靠(不安全)
    
            2. UDP协议的应用场景
                即时通讯(QQ,内网通,微信,陌陌...)
                在线网络视频
                网络电话
    
            3. UDP协议相关的类
                DatagramPacket:数据包对象:将数据,源以及目的地封装到数据包中
                    可以理解为:集装箱
                DatagramSocket:发送或接收对象
                    可以理解为:码头
    
        小结:
            1. UDP协议的特点:无连接协议,只管发送,不确认对方是否收到
                基于数据包传输,大小限制在64k,速度快但不可靠
    
     */
    public class Demo03 {
    }
    

4.UDP协议通信

package com.itheima._04UDP协议通信;

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

/**
    需求:使用UDP协议实现发送端和接收端程序:发送端发送数据,接收端接收数据。

    目标:使用UDP协议实现发送端程序(了解)

    讲解:
        1. UDP发送端实现步骤
            1. 创建数据包对象:用来封装要发送的数据
            2. 创建发送对象:用来发送数据包
            3. 调用发送对象的方法发送数据包
            4. 关闭发送对象释放资源

            网络编程就是Socket编程,Socket编程就是网络编程。
            Socket:套接字,插座

        2. DatagramPacket类常用构造方法
            * DatagramPacket(byte[] buf, int length, InetAddress address, int port)
                * 创建发送端数据包对象
                * buf:字节数组:要发送的实际内容
                * length:发送内容的长度,单位字节
                * address: 接收端的IP地址
                * port: 接收端的端口号
            *  DatagramPacket(byte[] buf, int length)
                * 创建接收端的数据包对象
                * buf:字节数组,用来存储接收到的数据
                * length:可以接收内容的长度,单位字节

        3. DatagramSocket类常用构造方法
            * DatagramSocket()
                * 创建发送端的Socket对象:相当于开启了一个进程,随机分配一个端口号。
            * DatagramSocket(int port)
                * 创建接收端的Socket对象并指定端口号。


        4. DatagramSocket类常用方法
            * void send(DatagramPacket dp) 发送数据包
            * void receive(DatagramPacket dp) 接收数据包

        5. InetAddress类静态方法
            * InetAddress对象代表一个IP地址
            * static InetAddress getByName(String host)
                * 根据ip地址字符串或主机名或域名获得IP地址对象
            * static InetAddress getLocalHost() 获得本机IP地址对象


    小结:
        1. UDP发送端实现步骤
             1. 创建数据包对象:用来封装要发送的数据
             2. 创建发送对象:用来发送数据包
             3. 调用发送对象的方法发送数据包
             4. 关闭发送对象释放资源
 */
public class Demo041 {
    public static void main(String[] args) throws Exception{
        // 0. 要发送的数据
        byte[] msg = "你好,UDP接收端,约吗".getBytes();
        // 1. 创建数据包对象:用来封装要发送的数据
        DatagramPacket dp = new DatagramPacket(msg, msg.length, InetAddress.getLocalHost(), 6666);
        // 2. 创建发送对象:用来发送数据包
        // 相当于开启了一个进程,随机分配一个端口号。
        DatagramSocket ds = new DatagramSocket();
        // 3. 调用发送对象的方法发送数据包
        ds.send(dp);
        // 4. 关闭发送对象释放资源
        ds.close();
    }
}
package com.itheima._04UDP协议通信;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

/**
    目标:使用UDP协议实现接收端程(了解)

    讲解:
        1. UDP接收端实现步骤
            1. 创建数据包对象:用来封装接收到的数据
            2. 创建接收对象
            3. 调用接收对象的方法接收数据包
            4. 关闭资源

    小结:
        1. UDP接收端实现步骤
             1. 创建数据包对象:用来封装接收到的数据
             2. 创建接收对象
             3. 调用接收对象的方法接收数据包
             4. 关闭资源
 */
public class Demo042 {
    public static void main(String[] args)throws Exception {
        // 0. 创建字节数组:存储接收到数据
        byte[] buf = new byte[1024];
        // 1. 创建数据包对象:用来封装接收到的数据
        DatagramPacket dp = new DatagramPacket(buf, buf.length);
        // 2. 创建接收对象
        DatagramSocket ds = new DatagramSocket(6666);
        System.out.println("接收端......");
        // 3. 调用接收对象的方法接收数据包
        // 阻塞方法
        ds.receive(dp);

        // 获得实际接收到的字节个数
        int len = dp.getLength();
        System.out.println("接收到了"+len+"个字节");
        // 将字节数组转换为字符串输出
        System.out.println("接收到内容:" + new String(buf,0,len));

        // 获得发送端的IP地址字符串
        // 127.0.0.1 本机ip地址
        String sendIP = dp.getAddress().getHostAddress();
        System.out.println("sendIP = " + sendIP);

        // 4. 关闭资源
        ds.close();
    }
}

5.TCP协议的概述

  • 特点

    • 面向连接的协议
    • 通过三次握手建立:形成数据传输通道
    • 通过四次挥手断开连接
    • 基于IO流进行数据传输
    • 传输数据大小没有限制
    • 因为面向连接,速度慢但可靠
  • 应用场景

    • 上传和下载文件
    • 发送和接收邮件
    • 远程登录:用户名和密码
  • TCP协议相关的类

    • Socket:客户端Socket对象:一个Socket对象就代表一个客户端程序

    • ServerSocket:服务器端Socket对象:一个ServerSocket对象就代表一个服务器端程序

      • package com.itheima._05TCP协议概述;
        
        /**
         目标:理解TCP协议的特点(记忆) 面试题
        
         讲解:
             1. TCP协议的特点
                面向连接的协议
                通过三次握手建立:形成数据传输通道
                通过四次挥手断开连接
                基于IO流进行数据传输
                传输数据大小没有限制
                因为面向连接,速度慢但可靠
        
        
             2. TCP协议的应用场景
                上传和下载文件
                发送和接收邮件
                远程登录:用户名和密码
        
             3. TCP协议相关的类
                Socket:客户端Socket对象:一个Socket对象就代表一个客户端程序
                ServerSocket:服务器端Socket对象:一个ServerSocket对象就代表一个服务器端程序
        
         小结:
             1. TCP协议的特点
                面向连接
                通过三次握手建立连接
                通过四次挥手断开连接
                基于IO流进行数据传输
                传输数据大小无限制
                速度慢,但可靠
         */
        public class Demo05 {
        }
        

6.TCP协议的通信

package com.itheima._06TCP协议通信;

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/**
    需求:使用TCP协议实现客端户和服务器端之间的数据传输。

    目标:使用TCP协议实现客户端程序

    讲解:
        1. TCP客户端代码实现步骤
            1. 创建客户端Socket对象:Socket
            2. 调用Socket对象的方法获得字节输出流:OutputStream
            3. 调用字节输出流的write方法输出数据到服务器端
            4. 调用Socket对象的方法获得字节输入流:InputStream
            5. 调用字节输入流的read方法读取服务器返回的数据
            6. 关闭Socket断开连接释放资源

        2. Socket类构造方法
            * Socket(String host, int port)
                * 根据IP地址和端口号创建客户端Socket
                * host:服务器端的IP地址
                * port:服务器端的端口号

        3. Socket类常用方法
            * OutputStream getOutputStream(); 获得字节输出流
            * InputStream getInputStream(); 获得字节输入流
 */
public class Demo061 {
    public static void main(String[] args) throws Exception{
        // 1. 创建客户端Socket对象:Socket
        Socket socket = new Socket("127.0.0.1", 9999);
        // 2. 调用Socket对象的方法获得字节输出流:OutputStream
        OutputStream out = socket.getOutputStream();
        // 3. 调用字节输出流的write方法输出数据到服务器端
        out.write("约吗".getBytes());
        // 4. 调用Socket对象的方法获得字节输入流:InputStream
        InputStream in = socket.getInputStream();
        // 5. 调用字节输入流的read方法读取服务器返回的数据
        // 创建字节数组:用来存储服务器返回的数据
        byte[] buf = new byte[1024];
        // 读取服务器返回数据
        int len = in.read(buf);
        System.out.println("len = " + len);
        System.out.println("服务器返回的数据:" + new String(buf,0,len));
        // 6. 关闭Socket断开连接释放资源
        socket.close();
    }
}
package com.itheima._06TCP协议通信;

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

/**
    目标:使用TCP协议实现服务器端程序

    讲解:
        1. TCP服务器端代码实现步骤
            1. 创建ServerSocket对象并指定端口号:开启了服务器端
            2. 调用ServerSocket对象accept方法:等待客户端连接并获得Socket对象
            3. 调用Socket对象getInputStream方法获得字节输入流
            4. 调用字节输入流对象的read方法读取客户端发送的数据
            5. 调用Socket对象的getOutputStream方法获得字节输出流
            6. 调用字节输出流的write方法返回数据给客户端
            7. 关闭服务器(实际开发不会关闭)

        2. ServerSocket类构造方法
            * ServerSocket(int port) 开启服务器并指定端口号

        3. ServerSocket类常用方法
            * Socket accept() 等待客户端连接并获得与客户端关联的socket对象
 */
public class Demo062 {
    public static void main(String[] args)throws Exception {
        // 1. 创建ServerSocket对象并指定端口号:开启了服务器端
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("开启了服务器...");
        // 2. 调用ServerSocket对象accept方法:等待客户端连接并获得Socket对象
        Socket socket = serverSocket.accept();
        // 3. 调用Socket对象getInputStream方法获得字节输入流
        InputStream in = socket.getInputStream();
        // 4. 调用字节输入流对象的read方法读取客户端发送的数据
        // 4.1 创建字节数组:用来存储客户端发送的数据
        byte[] buf = new byte[1024];
        // 4.2 读取客户端发送的数据
        int len = in.read(buf);
        System.out.println("len = " + len);
        System.out.println("客户端发送的数据:" + new String(buf,0,len));
        // 5. 调用Socket对象的getOutputStream方法获得字节输出流
        OutputStream out = socket.getOutputStream();
        // 6. 调用字节输出流的write方法返回数据给客户端
        out.write("不约儿童".getBytes());
       // 7. 关闭服务器(实际开发不会关闭)
        serverSocket.close();
    }
}

7.TCP文件上传案例

单用户上传

package com.itheima._07TCP文件上传案例.单用户上传;

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/**
    目标:实现上传文件客户端程序

    实现步骤:
        1. 创建客户端Socket对象指定服务器地址和端口号
        2. 创建字节输入流关联源文件:要上传的文件
        3. 调用Socket对象getOutputStream方法获得字节输出流
        4. 循环读取图片数据
        5. 将读取到的图片数据输出到服务器端
        6. 调用Socket对象的getInputStream方法获得字节输入流
        7. 调用字节输入流的read方法读取服务器返回的上传状态信息字符串
        8. 关闭字节输入流和Socket对象
 */
public class UploadFileClient {
    public static void main(String[] args) throws Exception{
        // 1. 创建客户端Socket对象指定服务器地址和端口号
        Socket socket = new Socket("192.168.90.72", 8888);
        // 2. 创建字节输入流关联源文件:要上传的文件
        FileInputStream fis = new FileInputStream("/Users/pkxing/documents/a.jpg");
        // 3. 调用Socket对象getOutputStream方法获得字节输出流
        OutputStream out = socket.getOutputStream();
        // 4. 循环读取图片数据
        // 4.1 创建字节数组:存储读取到的图片数据
        byte[] buf = new byte[1024];
        // 4.2 定义整型变量:接收实际读取到的字节个数
        int len = -1;
        while((len = fis.read(buf)) != -1){ // len = -1
            // 5. 将读取到的图片数据输出到服务器端
            out.write(buf, 0, len);
        }
        // out.write("-1".getBytes());
        // 告诉服务器端数据传输完毕:输出一个结束标记给服务器端
        socket.shutdownOutput();

        // 关闭流释放资源
        fis.close();
        // 6. 调用Socket对象的getInputStream方法获得字节输入流
        InputStream in = socket.getInputStream();
        // 7. 调用字节输入流的read方法读取服务器返回的上传状态信息字符串
        len = in.read(buf);
        System.out.println(new String(buf,0,len));
        // 8. 关闭Socket对象
        socket.close();
    }
}

package com.itheima._07TCP文件上传案例.单用户上传;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;

/**
    目标:实现上传文件服务器程序--单用户上传

    实现步骤
        1. 创建ServerSocket对象并指定端口号:开启服务器
        2. 调用ServerSocket对象的accept方法:等待客户端连接并获得Socket对象
        3. 调用Socket对象的getInputStream方法:获得字节输入流:InputStream
        4. 创建字节输入流关联目标文件:FileOutputStream
        5. 循环读取客户端发送的图片数据
        6. 将图片输出输出到目标文件中
        7. 调用Socket对象的getOutputStream方法:获得字节输出流:OutputStream
        8. 调用字节输出流的write方法返回数据给客户端
        9. 关闭流和服务器
 */
public class UploadFileServer {
    public static void main(String[] args) throws Exception{
        // 1. 创建ServerSocket对象并指定端口号:开启服务器
        ServerSocket serverSocket = new ServerSocket(8888);
        System.out.println("开启了服务器...");
        // 2. 调用ServerSocket对象的accept方法:等待客户端连接并获得Socket对象
        Socket socket = serverSocket.accept();
        File destFile = null;
        try{
           // 3. 调用Socket对象的getInputStream方法:获得字节输入流:InputStream
           InputStream in = socket.getInputStream();
           // 4. 创建字节输出流关联目标文件:FileOutputStream
           // 4.1 创建随机数对象
           Random r = new Random();
           // 4.2 随机产生一个整数
           int randomNumber = r.nextInt(999999999);
           // 4.3 获得当前时间毫秒值和整数进行拼接:得到文件名
           String fileName = System.currentTimeMillis()+""+randomNumber+".jpg"; // 15665352414.jpg
           // 4.4 创建文件对象
            destFile = new File("/Users/pkxing/documents/aaa/", fileName);
           FileOutputStream fos = new FileOutputStream(destFile);

           // 5. 循环读取客户端发送的图片数据
           // 5.1 创建字节数组:用来存储客户端发送的图片数据
           byte[] buf = new byte[1024];
           // 5.2 定义整型变量:接收实际读取到的字节个数
           int len = -1;
           while ((len = in.read(buf)) !=-1) {
               // 6. 将图片输出输出到目标文件中
               fos.write(buf, 0,len);
           }
           // 关闭流释放资源
           fos.close();
           // 获得客户端ip地址
           String clientIP = socket.getInetAddress().getHostAddress();
           System.out.println("恭喜ip为:"+ clientIP +"用户上传成功");

           // 7. 调用Socket对象的getOutputStream方法:获得字节输出流:OutputStream
           OutputStream out = socket.getOutputStream();
           // 8. 调用字节输出流的write方法返回数据给客户端
           out.write("上传成功".getBytes());
       } catch(Exception e){
            // 返回上传失败给客户端
           // 7. 调用Socket对象的getOutputStream方法:获得字节输出流:OutputStream
           OutputStream out = socket.getOutputStream();
           // 8. 调用字节输出流的write方法返回数据给客户端
           out.write("上传失败".getBytes());
           destFile.delete();
       }
    }
}

多用户上传

package com.itheima._07TCP文件上传案例.多用户上传;

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/**
    目标:实现上传文件客户端程序
 */
public class UploadFileClient {
    public static void main(String[] args) throws Exception{
        // 1. 创建客户端Socket对象指定服务器地址和端口号
        Socket socket = new Socket("192.168.90.72", 8888);
        // 2. 创建字节输入流关联源文件:要上传的文件
        FileInputStream fis = new FileInputStream("/Users/pkxing/documents/a.jpg");
        // 3. 调用Socket对象getOutputStream方法获得字节输出流
        OutputStream out = socket.getOutputStream();
        // 4. 循环读取图片数据
        // 4.1 创建字节数组:存储读取到的图片数据
        byte[] buf = new byte[1024];
        // 4.2 定义整型变量:接收实际读取到的字节个数
        int len = -1;
        while((len = fis.read(buf)) != -1){ // len = -1
            // 5. 将读取到的图片数据输出到服务器端
            out.write(buf, 0, len);
        }
        // out.write("-1".getBytes());
        // 告诉服务器端数据传输完毕:输出一个结束标记给服务器端
        socket.shutdownOutput();

        // 关闭流释放资源
        fis.close();
        // 6. 调用Socket对象的getInputStream方法获得字节输入流
        InputStream in = socket.getInputStream();
        // 7. 调用字节输入流的read方法读取服务器返回的上传状态信息字符串
        len = in.read(buf);
        System.out.println(new String(buf,0,len));
        // 8. 关闭Socket对象
        socket.close();
    }
}

package com.itheima._07TCP文件上传案例.多用户上传;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;

/**
    目标:实现上传文件服务器程序--多用户上传

    实现步骤
        1. 开启一个服务器程序
        2. 使用死循环保证服务器程序永不退出
        3. 等待客户端连接,创建线程处理用户的上传文件请求
 */
public class UploadFileServer {
    public static void main(String[] args) throws Exception{
       // 1. 开启一个服务器程序
        ServerSocket serverSocket = new ServerSocket(8888);
        System.out.println("开启了服务器...");
        // 2. 使用死循环保证服务器程序永不退出
        while (true){
            // 3. 等待客户端连接
            Socket socket = serverSocket.accept();
            // 4. 创建线程处理用户的上传文件请求
            new UploadThread(socket).start();
        }
    }
}

package com.itheima._07TCP文件上传案例.多用户上传;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Random;

/**
 上传线程
 */
public class UploadThread extends Thread {
    private Socket socket;

    public UploadThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try{
            // 3. 调用Socket对象的getInputStream方法:获得字节输入流:InputStream
            InputStream in = socket.getInputStream();
            // 4. 创建字节输出流关联目标文件:FileOutputStream
            // 4.1 创建随机数对象
            Random r = new Random();
            // 4.2 随机产生一个整数
            int randomNumber = r.nextInt(999999999);
            // 4.3 获得当前时间毫秒值和整数进行拼接:得到文件名
            String fileName = System.currentTimeMillis()+""+randomNumber+".jpg"; // 15665352414.jpg
            // 4.4 创建文件对象
            File destFile = new File("/Users/pkxing/documents/aaa/", fileName);
            FileOutputStream fos = new FileOutputStream(destFile);

            // 5. 循环读取客户端发送的图片数据
            // 5.1 创建字节数组:用来存储客户端发送的图片数据
            byte[] buf = new byte[1024];
            // 5.2 定义整型变量:接收实际读取到的字节个数
            int len = -1;
            while ((len = in.read(buf)) !=-1) {
                // 6. 将图片输出输出到目标文件中
                fos.write(buf, 0,len);
            }
            // 关闭流释放资源
            fos.close();
            // 获得客户端ip地址
            String clientIP = socket.getInetAddress().getHostAddress();
            System.out.println("恭喜ip为:"+ clientIP +"用户上传成功");

            // 7. 调用Socket对象的getOutputStream方法:获得字节输出流:OutputStream
            OutputStream out = socket.getOutputStream();
            // 8. 调用字节输出流的write方法返回数据给客户端
            out.write("上传成功".getBytes());
        } catch(Exception e){
            // 返回上传失败给客户端
            try{
                // 7. 调用Socket对象的getOutputStream方法:获得字节输出流:OutputStream
                OutputStream out = socket.getOutputStream();
                // 8. 调用字节输出流的write方法返回数据给客户端
                out.write("上传失败".getBytes());
            } catch(Exception ee){

            }
        }
    }
}

8.模拟BS服务器案例

package com.itheima._08模拟BS服务器案例;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
    目标:模拟网站BS服务器,使用浏览器访问自己编写的服务端程序,查看网页效果。

    讲解:
        1. 准备网页数据,保存到baidu.txt文本中。

        2. 当使用浏览器访问服务端程序时,返回网页数据显示。

            localhost 代表本机域名
            http://127.0.0.1:6666/
 */
public class Demo08 {
    public static void main(String[] args) throws Exception {
        // 开启服务器程序:ServerSocket对象
        ServerSocket serverSocket = new ServerSocket(6666);
        System.out.println("开启服务器....");
        // 等待浏览器连接得到Socket对象
        Socket socket = serverSocket.accept();

        // 获得字节输入流
        InputStream in = socket.getInputStream();
        byte[] buf = new byte[1024];
        int len = in.read(buf);
        System.out.println(len);
        System.out.println(new String(buf,0,len));

        // 创建字符缓冲输入流
        BufferedReader br = new BufferedReader(new FileReader("day11_课堂代码/baidu.txt"));
        // 读取网页文件的数据
        String line = br.readLine();
        // 获得字节输出流
        OutputStream out = socket.getOutputStream();
        // 将网页文件的数据返回给浏览器解析显示
        out.write(line.getBytes());
        // 关闭流释放资源
        br.close();
        // 关闭服务器
        serverSocket.close();
    }
}

/*
   网页数据:使用标签编写代码,浏览器负责解析标签
    <!DOCTYPE html><!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>&copy;2017&nbsp;Baidu&nbsp;<a href=http://www.baidu.com/duty/>使用百度前必读</a>&nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a>&nbsp;京ICP证030173号&nbsp; <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
*/

9.junit基本使用

package com.itheima._09junit基本使用;

/**
    目标:能够说出junit的作用

    讲解:
        1. 什么是Junit
            Junit是第三方Java语言编写的单元测试工具。
            框架 ==> 类的集合 ==> 类库   junit.jar

            什么是单元:在Java中一个类就是一个单元。
            单元测试:开发者编写的一小段代码对某个类中的某个方法进行测试,保证方法的正确性和
                稳定性。

        2. Junit的作用
            对类的方法进行测试,保证方法的正确性和稳定性,最大限避免出现bug。

        在实际开发,分层开发的
        * 表现层:直接和用户打交道,展示数据给用户看和接收用户输入的数据。
        * 业务层:处理业务逻辑的
        * 数据访问层:直接和数据库打交道:对数据库执行增删改查操作

    小结:
        1. Junit的作用:用来对类的方法进行测试,保证方法的正确性和稳定性,最大限避免出现bug。
 */
public class Demo091 {
}

package com.itheima._09junit基本使用;

/**
    目标:掌握junit常用注解

    讲解:
        Junit4.0
            @Before: 用来修饰方法,该方法会在每一个测试方法执行之前执行1次。
            @After: 用来修饰方法,该方法会在每一个测试方法执行之后执行1次。
        Junit5.0
            @BeforeEach: 用来修饰方法,该方法会在每一个测试方法执行之前执行1次。
            @AfterEach: 用来修饰方法,该方法会在每一个测试方法执行之后执行1次。

    小结:
        1. @Before注解修饰方法的执行时机:每个测试方法执行之前执行1次
        2. @After注解修饰方法的执行时机:每个测色方法执行之后执行1次
 */
public class Demo093 {

}

package com.itheima._09junit基本使用;

/**
 * @author pkxing
 * @version 1.0
 * @Package com.itheima._09junit基本使用
 * @date 2019-08-13  16:39
 */
public class Student {
}

package com.itheima._09junit基本使用;

/**
 * 业务类:对学生进行增删改查操作
 */
public class StudentDao {
    // 业务方法:保存学生
    public boolean saveStudent(Student stu){
        System.out.println("保存学生:" + stu);
        return true;
    }

    // 业务方法:根据id删除学生
    public void deleteById(int id){
        System.out.println("删除id为"+id+"学生");
    }

}

package com.itheima._09junit基本使用;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

/**
    目标:能够使用junit进行单元测试

    讲解:
        1. Junit的使用步骤
            1.1 编写业务类:实现某一个业务逻辑的类,比如要对象学生进行增删改查
                编写业务方法:实现某一个功能的方法,比如添加学生

            1.2 编写测试类:对业务类中的方法进行测试
                编写测试方法:编程测试代码测试业务方法

        2. 测试方法的要求
            测试类命名要求:一般以Test开头,以业务类名结尾
                比如业务类名:StudentDao,那么测试类名:TestStudentDao
            测试方法的命名要求:一般以test,以业务方法名结尾
                比如业务方法名:saveStudent,则测试方法名为:testSaveStudent
            测试方法的声明要求:
                必须是public修饰,必须没有返回值,必须没有参数,必须使用@Test注解修饰

        3. 测试方法的运行方式
            选中测试方法名 --> 右键 --> run '测试方法名'  执行选中的测试方法
            选中测试类名 --> 右键 --> run '测试类名'  执行当前测试类的所有测试方法
            选中项目名 --> 右键 --> run 'All Tests'  执行当前项目下所有测试类中的所有测试方法

        4. 如何查看测试结果
            绿色:代表测试通过,没有异常
            红色:代表测试失败,有异常

    小结:
        1. 测试方法的要求
            必须是public,必须没有返回值,必须没有参数,必须使用@Test注解

 */
// 测试类
public class TestStudentDao {


    // 成员变量
    StudentDao stuDao = null;

    @Before // 该方法会在每一个测试方法执行之前执行1次。
    public void init(){
        System.out.println("init");
        // 创建数据访问层对象
        stuDao = new StudentDao();
    }

    @After // 该方法会在每一个测试方法执行之后执行1次。
    public void close(){
        System.out.println("close");
        stuDao = null;
    }

    // 测试方法:编写测试代码对业务方法进行测试
    @Test
    public void testSaveStudent(){
        // 创建学生
        Student stu = new Student();
        // 保存学生信息
        boolean result = stuDao.saveStudent(stu);
        /*
            断言:预先判断某个条件一定成立,如果条件不成立则直接抛出异常
            Assert.assertEquals(String message, Object expected , Object actual);
                message:提示信息字符串
                expected:期望值
                actual:实际值
         */
        Assert.assertEquals("期望值和实际值不一致", true, result);
        System.out.println("result = " + result);
    }

    @Test
    public void testDeleteById(){
        stuDao.deleteById(1);
    }
}

10.总结

/**

     - 能够辨别UDP和TCP协议特点
        UDP协议
            面向无连接
            只管发送,不确认是否收到
            速度快但不可靠
            基于数据包进行传输
            数据包大小限制在64k

        TCP协议           TCP ==> Transfer Control Protocol 传输控制协议
            面向连接协议
            通过三次握手建立连接
            通过四次挥手断开连接
            基于IO流进行传输
            传输数据大小无限制
            速度慢但可靠

     - 能够说出TCP协议下两个常用类名称
        Socket:代表客户端程序
        ServerSocket:代表服务器端程序

     - 能够编写TCP协议下字符串数据传输程序
        TCP客户端实现步骤
        1.创建客户端Socket关联服务器ip和端口号
        2.获得字节输出流对象
        3.调用字节输出流对象的write输出数据
        4.获得字节输入流对象
        5.调用字节输入流对象的read方法读取服务器返回数据
        6.关闭socket断开连接

        TCP服务器端实现步骤
        1. 创建服务器端ServerSocket对象并指定端口号
        2. 调用accept方法等待客户端连接并获得Socket对象
        3. 获得字节输入流对象
        4. 调用字节输入流对象的read方法读取客户端发送的数据
        5. 获得字节输出流对象
        6. 调用字节输出流对象的write输出数据给客户端
        7. 关闭服务器端

     - 能够理解TCP协议下文件上传案例
        * 参考代码 类似文件复制

     - 能够理解TCP协议下模拟B\S服务器案例
        * 参考代码

    知识回顾
        1. 缓冲流原理:内部准备了一个缓冲区数组,用来临时存储数据,当数组满了或调用close或flush方法
                     才会将数组的数据输出到目标文件中:减少底层资源的调用次数,提高读写速度。
            字节缓冲输入流:BufferedInputStream  包装  FileInputStream   方法:read
            字节缓冲输入流:BufferedOutputStream  包装 FileOutputStream  方法:write
            字符缓冲输入流:BufferedReader  包装  FileReader   方法:readLine  read
            字符缓冲输出流:BufferedWriter  包装  FileWriter   方法:newLine   write

        2. 转换流:本质就是字符流
            字符转换输入流:InputStreamReader 包装 FileInputStream
                    转换过程:字节转字符
                    1. 先通过字节输入流FileInputStream从目标文件中读取数据,读取到的是二进制数据
                    2. 然后将二进制数据交给字符转换输入流InputStreamReader查询码表解码成字符。

            字符转换输出流:OutputStreamWriter  包装 FileOutputStream
                    转换过程:字符转字节
                    1. 先通过字符转换输出流OutputStreamWriter将字符查询指定的码表转换为二进制数据
                    2. 然后将二进制数据交给字节输出流FileOutputStream输出目标文件中

        3. 序列化流
            实现对象序列化操作:保存自定义对象到文件中  ObjectOutputStream  方法:writeObject(Object obj)
            实现对象反序列化操作:从文件中读取自定义对象 ObjectInputStream  方法:Object readObject()
            自定义对象要想实现序列化则必须要实现一个Serializable接口,并自定义序列号。

        4. 打印流:方便原样直接输出各种数据类型的值。

        5. Properties集合
            保存键值对:String setProperty(String key,String value)
            根据键获得值:String getProperty(String key)
            根据键删除键值对:String remove(String key)
            获得键集合:Set<String> stringPropertyNames();

            保存集合数据到文件中:store(OutputStream out,String comments);
            从文件中读取数据到集合中:load(InputStream in)
            属性文件中键值对的格式:一个键值对占据一行:键=值

*/
public class Demo10 {
}


## 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值