A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 小石姐姐 于 2018-12-6 17:11 编辑

day11 网络编程今日内容    理解网络通信的底层
    基础概念
            软件架构:
                    CS: Client客户端, Server服务器
                    BS: Browser浏览器, Server服务器
            网络通信三要素
            TCP通信协议/UDP协议
    网络编程        
            Socket: 套接字  客户端
            ServerSocket   服务端
    案例
            文件上传
            模拟Web服务器网络编程基础软件结构介绍知识点:    什么是CS结构, 哪些软件是CS结构
    什么是BS结构, 哪些软件是BS结构
    什么是网络编程总结:    C/S结构:
            全称为Client/Server结构, 是指 客户端 和 服务器 结构
            常见程序有QQ, 迅雷等软件
    B/S结构:
            全称为Browser/Server结构, 是指 浏览器 和 服务器 结构
            常见浏览器有IE, 谷歌, 火狐等
    网络编程: 在一定的"协议"下, 实现两台计算机的通信的程序
    中国人  ---翻译--->  美国
    中国人学英语  ----> 美国人
    计算机A  ------> 计算机B  补充:    网络通信协议知识点:    什么是通信协议
    什么是TCP/IP协议总结:    网络通信协议:
            通信协议是计算机必须遵守的规则, 只有遵守这些规则, 计算机之间才能进行通信.
            协议中对数据的传输格式, 传输速率, 传输步骤等做了统一规定, 通信双方必须同时遵守, 最终完成数据交换
            (类似于一种语言, 语法语速做了规定)
    TCP/IP协议:
            Transmission Control Protocol/Internet Protocol, 传输控制协议/因特网互联协议.
            它定义了计算机如何连入因特网, 以及数据如何在它们之间传输的标准. 它的内部包含一系列的用于处理数据通信的协议, 并采用了4层的分层模型, 每一层都呼叫它的下一层所提供的协议来完成自己的需求补充:    网络通信协议分类知识点:    传输层的网络通信协议分为哪两种
    UDP协议有什么特点
    TCP协议有什么特点总结:    UDP: User Datagram Protocol, 用户数据报协议
            特点:
                    1. 无连接的不可靠协议
                    2. 数据按包发送, 64K一个包
                    3. 速度快效率高, 容易丢包
            用于视频直播, 网络电话
    TCP: Transmission Control Protocol, 传输控制协议
            特点:
                    1. 需要建立连接的可靠协议  电话
                    2. 数据传输无大小限制
                    3. 速度慢效率低   重发机制
            用于文件下载, 浏览网页
    TCP通信的三次握手: TCP协议中, 在发送数据的准备阶段, 客户端与服务器之间的三次交互, 以保证连接的可
    靠
            1. 客户端向服务端发送验证信息, 等待服务器确认
            2. 服务端收到验证信息后, 回复客户端验证信息, 同时发送自己的一条验证信息
            3. 客户端收到服务端回复的信息, 确认自己之前发的信息无误, 并再次向服务器发回服务端的验证信息补充:    网络编程三要素: IP地址知识点:    网络编程的三要素分别是什么
    什么是IP地址总结:    网络编程三要素:
            1. 通信协议  TCP
            2. IP地址
            3. 端口号
            IP地址: 互联网协议地址(Internet Protocol Address). 是网络中计算机的唯一标识
            版本:
                    IPv4: 192.168.1.2
                    IPv6: ABCD:EF01:2345:6789:ABCD:EF01:2345:6789
            特殊的IP地址: "127.0.0.1", "localhost", 都代表自己的电脑
    常用DOS命令:
            // 查看自己电脑的IP地址
            ipconfig
            // 查看是否能连接到指定IP地址
            ping IP地址
            ping 192.168.31.2补充:    网络三要素: 端口号知识点:    什么是端口号总结:    端口号: 计算机中进程的唯一标识
            端口号的取值范围: 0~65535的整数, 其中0~1024不建议使用
    注意:
            通信的两端是2个计算机中的2个程序在相互通信, 所以2个程序都要有端口号. 端口号可以相同, 也可以不同, 相互之间能识别就行补充:    域名: 便于记忆的主机名称, 可以解析到某个IP地址, 这样通过域名就能找到对应的IP地址
    www.baidu.com -> 111.13.100.92
    http:// www.baidu.com :80
    ------  ------------- ---
     协议      IP地址      端口TCP通信TCP通信程序概述(上)知识点:    TCP通信时, 客户端和服务端应该谁先启动
    Java中提供了哪个类代表客户端, 哪个类代表服务端
    客户端和服务端之间传输数据, 要通过什么方式进行
    一个服务端可以和多个客户端通信吗总结:    java.net.ServerSocket类: TCP服务端
            // 构造方法
            ServerSocket(int port): 创建一个TCP服务端, 并监听指定端口
            // 成员方法
            Socket accept(): 监听数据, 会阻塞. 收到数据后返回Socket对象
            void close(): 关闭服务端ServerSocket
    java.net.Socket类: TCP客户端
            // 构造方法
            Socket(String ip, int port): 创建TCP客户端对象
            // 成员方法
            OutputStream getOutputStream(): 获取输出流对象, 用于发送数据
            InputStream getInputStream(): 获取输入流, 用于接收数据
            void shutdownOutput(): 关闭输出流, 发送结束标记
            void close(): 关闭客户端Socket
    TCP严格区分为 客户端(Client) 与 服务端(Server)
    两端通信时步骤:
            1. 服务端程序需要先启动, 等待客户端的连接
            2. 客户端主动连接服务器端, 连接成功才能通信. 服务端不可以主动连接客户端
    两端之间以 "IO字节流" 进行通信
    一个服务端可以和多个客户端同时通信补充:    TCP通信方式概述(下)知识点:    一个服务端和多个客户端进行通信时, 如何区分客户端, 要有多少个流对象总结:    服务端(ServerSocket)可以通过 accept() 方法等待一个客户端(Socket)主动连接, 从而得到一个客户端对象(Socket), 来识别不同的客户端
    服务端(ServerSocket)没有IO流, 是通过获取到"每个客户端对象(Socket)的IO流对象"来进行通信的.
            使用"客户端的InputStream"读取客户端发来的数据
            使用"客户端的OutputStream"向客户端回写数据补充:    TCP程序: 客户端代码实现知识点:    如何通过代码实现TCP客户端总结:    java.net.Socket类: TCP客户端
            // 构造方法
            Socket(String 服务端ip, int 服务端port): 创建TCP客户端对象, 同时尝试连接到指定的服务端
                    (客户端也会获取系统随机分配的一个端口号)
            // 成员方法
            OutputStream getOutputStream(): 获取输出流对象, 用于发送数据
            InputStream getInputStream(): 获取输入流, 用于接收数据
            void shutdownOutput(): 关闭输出流, 告知服务端数据发送完毕, 结束标记-1
            void close(): 关闭客户端Socket, 告知服务端数据发送完毕
    实现步骤:
            1.创建一个客户端对象 Socket, 构造方法传入服务器的IP地址和端口号
            2.使用Socket对象中的方法 getOutputStream() 获取网络字节输出流OutputStream对象
            3.使用网络字节输出流OutputStream对象中的方法 write(), 给服务器发送数据
            4.使用Socket对象中的方法 getInputStream() 获取网络字节输入流InputStream对象
            5.使用网络字节输入流InputStream对象中的方法 read(), 读取服务器回写的数据
            6.释放资源(Socket)
    注意:
            1.客户端和服务器端进行交互, 必须使用Socket中提供的网络流, 不能使用自己创建的流对象
            2.当我们创建客户端对象Socket的时候, 就会去请求服务器和服务器经过3次握手建立连接通路
                    这时如果服务器没有启动, 那么就会抛出异常ConnectException: Connection refused: connect
                    如果服务器已经启动, 那么就可以进行交互了
                    // 创建客户端Socket对象, 指定要连接的服务端的IP和端口号
            Socket socket = new Socket("127.0.0.1", 8888);
            // 向服务端发送数据
            OutputStream os = socket.getOutputStream();
            os.write("你好服务器".getBytes());
            // 释放资源
            socket.close();补充:    5分钟练习: 编写TCP客户端    需求:
    编写TCP客户端, 连接服务端的IP是"127.0.0.1", 端口是8888, 发送"你好服务器"代码:    public class TCPClient {
        public static void main(String[] args) throws IOException {
            // 1. 创建客户端Socket对象, 指定要连接的服务端的IP地址和端口号
            // 创建Socket对象时, 会自动去连接服务端, 如果服务端没有启动, 或IP地址或端口错误, 则抛异常: java.net.ConnectException: Connection refused: connect
            Socket socket = new Socket("127.0.0.1", 8888);  // 127.0.0.1 表示自己电脑的IP地址
            // 2. 获取网络字节输出流对象
            OutputStream os = socket.getOutputStream();
            // 3. 通过网络字节输出流对象发送(写)数据
            os.write("你好服务器".getBytes
            // 待做: 接收服务器返回的
            // 释放资源(关闭Socket同时会关闭流对象)
            socket.close();
        }
    }TCP程序: 服务器端代码实现知识点:    如何通过代码实现TCP服务端总结:    java.net.ServerSocket类: TCP服务端
            // 构造方法
            ServerSocket(int 服务端自己用的port): 创建一个TCP服务端, 并监听指定端口
            // 成员方法
            Socket accept(): 等待客户端连接, 会阻塞. 客户端连接后返回客户端的Socket对象
            void close(): 关闭服务端ServerSocket, 断开所有流
    服务器的实现步骤:
            1.创建服务器ServerSocket对象并指定服务器占用的端口号
            2.使用ServerSocket对象中的方法 accept(), 获取到请求的客户端对象Socket
            3.使用Socket对象中的方法 getInputStream() 获取网络字节输入流InputStream对象
            4.使用网络字节输入流InputStream对象中的方法 read(), 读取客户端发送的数据
            5.使用Socket对象中的方法 getOutputStream() 获取网络字节输出流OutputStream对象
            6.使用网络字节输出流OutputStream对象中的方法 write(), 给客户端回写数据
            7.释放资源(Socket,ServerSocket)
  // 创建服务端ServerSocket对象, 并指定自己监听的端口
            ServerSocket server = new ServerSocket(8888);
            // 调用accept方法等待客户端连接
            Socket socket = server.accept();
            // 通过客户端获取输入流, 读取客户端发来的数据
            InputStream is = socket.getInputStream();
            byte[] bytes = new byte[1024];
            int len = is.read(bytes);
            System.out.println(new String(bytes, 0, len));
            // 通过客户端获取输出流, 向客户端回写数据
            OutputStream os = socket.getOutputStream();
            os.write("收到谢谢".getBytes());
            // 释放资源
            socket.close();
            // server.close();  // 客户端一般不关闭补充:    5分钟练习: 编写TCP服务端, 补全TCP客户端接收代码    需求:
    编写TCP服务端代码, 监听8888端口, 接收客户端发来的消息打印到控制台, 然后向客户端回写"收到谢谢"
    补全TCP客户端接收数据的代码, 将服务器回写的数据打印到控制台代码:    // TCP协议的服务端
   
[AppleScript] 纯文本查看 复制代码
public class TCPServer {
        public static void main(String[] args) throws IOException {
            // 创建服务端对象, 并指定要使用的端口号
            ServerSocket serverSocket = new ServerSocket(8888);
            System.out.println("服务端已启动...")
            // 调用accept方法来等待客户端连接
            Socket clientSocket = serverSocket.accept();
            // 通过客户端socket对象获取网络字节输入流, 用来读取数据
            InputStream is = clientSocket.getInputStream();
            // 通过流读取数据, 一次读一个byte数组, 因为发送的字符串内容少, 所以一个数组读一次就够了
            byte[] bytes = new byte[1024];
            int len;
            len = is.read(bytes);
            // 将读取到的字节数组转换为字符串, 读到多少转换多少, 不要全转
            String s = new String(bytes, 0, len);
            //System.out.println("[服务端收到信息]:来自" + clientSocket.getInetAddress().getHostAddress());
            System.out.println("[服务端收到信息]:" + s);
            // 通过客户端socket对象获取网络字节输出流, 用来发送数据
            OutputStream os = clientSocket.getOutputStream();
            os.write("收到谢谢!".getBytes());
            // 关闭
            clientSocket.close();
            serverSocket.close();
        }

   
   
[Java] 纯文本查看 复制代码
 public class TCPClient {
        public static void main(String[] args) throws IOException {
            // 1. 创建客户端Socket对象, 指定要连接的服务端的IP地址和端口号
            // 创建Socket对象时, 会自动去连接服务端, 如果服务端没有启动, 或IP地址或端口错误, 则抛异常: java.net.ConnectException: Connection refused: connect
            Socket socket = new Socket("127.0.0.1", 8888);  // 127.0.0.1 表示自己电脑的IP地址
            // 2. 获取网络字节输出流对象
            OutputStream os = socket.getOutputStream();
            // 3. 通过网络字节输出流对象发送(写)数据
            os.write("你好服务器".getBytes());
            // 获取网络字节输入流对象, 接收服务器返回的数据
            InputStream is = socket.getInputStream();
            byte[] bytes = new byte[0124];
            int len;
            len = is.read(bytes);
            // 将读取到的字节转换为字符串
            String s = new String(bytes, 0, len);
            System.out.println("[客户端收到的数据]:" + s);
            // 释放资源(关闭Socket同时会关闭流对象)
            socket.close();
        }

    }文件上传案例文件上传原理知识点:    客户端上传文件到服务器的流程是什么
    总结:    补充:    文件上传案例: 客户端代码实现知识点:    文件上传的客户端, 如何用流读取本地文件, 并将读到的byte交给Socket的OutputStream发送
    总结:    使用FileInputStream读图片
    使用OutputStream发送图片到服务端
    边读边发补充:    5分钟练习: 实现客户端上传图片    需求:
    编写客户端上传文件代码
    实现步骤:
        1.创建一个本地字节输入流FileInputStream对象, 构造方法中绑定要读取的数据源
        2.创建一个客户端Socket对象, 构造方法中绑定服务器的IP地址和端口号
        3.使用Socket中的方法getOutputStream, 获取网络字节输出流OutputStream对象
        4.使用本地字节输入流FileInputStream对象中的方法read, 读取本地文件
        5.使用网络字节输出流OutputStream对象中的方法write, 把读取到的文件上传到服务器
        6.使用Socket中的方法getInputStream, 获取网络字节输入流InputStream对象
        7.使用网络字节输入流InputStream对象中的方法read读取服务回写的数据
        8.释放资源(FileInputStream, Socket)代码:    // 文件上传TCP客户端
[Java] 纯文本查看 复制代码
 public class FileUploadClient {
        public static void main(String[] args) throws IOException{
            /*
                1. 读取磁盘文件, 发送到服务端
             */
            // 创建文件字节输入流对象, 用来读取文件
            FileInputStream fis = new FileInputStream("day11\\小岳岳.jpg");  // 指向要上传的图片文件
            // 创建客户端Socket对象, 连接服务端的地址
            Socket socket = new Socket("127.0.0.1", 9999);
            // 获取网络字节输出流, 用来向服务端发送数据
            OutputStream os = socket.getOutputStream();
            // 边读磁盘文件, 边向服务端发送数据. 一次读写一个byte数组
            byte[] bytes = new byte[1024];
            int len;
            while ((len = fis.read(bytes)) != -1) {
                // 读到多少数据, 就写多少
                os.write(bytes, 0, len);
            }
            /*
                2. 读取服务端返回的信息, 打印出来
             */
            // 获取网络字节输入流, 用来读取服务端返回的上传结果
            InputStream is = socket.getInputStream();
            // 边读服务器返回的数据, 边转换为字符串打印. 一次读一个byte数组
            // 因为bytes数组和len上面已经定义过了, 所以我们可以直接使用
            while ((len = is.read(bytes)) != -1) {  // 注意!! 这里是用网络输入流读, 不要把对象写错
                // 读到多少转换多少
                String s = new String(bytes, 0, len);
                System.out.print(s);
            }
            /*
                3. 释放资源
             */
            fis.close();     // 自己创建的文件流要关闭
            socket.close();  // 网络流通过socket来关闭
        }
    }

   文件上传案例: 服务器端代码实现知识点:    文件上传服务端如何接收文件进行保存, 如何返回响应
    总结:    使用InputStream从客户端接收数据
    使用FileOutputStream写图片
    边收边写补充:    File file = new File("d:\\upload")
    file + "\\1.jpg"
        d:\\upload\\1.jpg5分钟练习: 实现服务端接收图片    需求:
    编写文件上传服务器代码, 将上传的文件保存到当前模块下的upload目录中
    实现步骤:
        1.创建一个服务器ServerSocket对象,和系统要指定的端口号
        2.使用ServerSocket对象中的方法accept,获取到请求的客户端Socket对象
        3.使用Socket对象中的方法getInputStream,获取到网络字节输入流InputStream对象
        4.判断"模块名\\upload"文件夹是否存在,不存在则创建
        5.创建一个本地字节输出流FileOutputStream对象,构造方法中绑定要输出的目的地
        6.使用网络字节输入流InputStream对象中的方法read,读取客户端上传的文件
        7.使用本地字节输出流FileOutputStream对象中的方法write,把读取到的文件保存到服务器的硬盘上
        8.使用Socket对象中的方法getOutputStream,获取到网络字节输出流OutputStream对象
        9.使用网络字节输出流OutputStream对象中的方法write,给客户端回写"上传成功"
        10.释放资源(FileOutputStream,Socket,ServerSocket)代码:    // 文件上传服务端
  
           
[Java] 纯文本查看 复制代码
  public class FileUploadServer {
        public static void main(String[] args) throws IOException {
            /*
                服务端接收上传数据, 写到服务端的磁盘
             */
            // 创建服务端
            ServerSocket serverSocket = new ServerSocket(9999);
            System.out.println("文件上传服务端已启动....");
            // 等待客户端连接
            Socket clientSocket = serverSocket.accept();
            // 创建上传文件的目录
            File uploadDir = new File("day11\\upload");
            if (!uploadDir.exists()) {
                uploadDir.mkdirs();
            }
 // 获取网络字节输入流, 用来读取客户端发来的文件数据
            InputStream is = clientSocket.getInputStream();
            // 创建文件字节输出流, 用来向服务端磁盘写文件数据
            FileOutputStream fos = new FileOutputStream(uploadDir + "\\小岳岳.jpg");
            // 一次读写一个字节数组
            byte[] bytes = new byte[1024];
            int len;
            while ((len = is.read(bytes)) != -1) {
                // 读多少, 写杜少
                fos.write(bytes, 0, len);
            }
   
            /*
                服务端向客户端回写上传成功
             */
            clientSocket.getOutputStream().write("上传成功".getBytes());
   
            /*
                释放资源
             */
            fos.close();
            clientSocket.close();
            serverSocket.close();
        }
    }

文件上传案例: 阻塞问题知识点:    Socket流如何发送结束标记

    }模拟B/S案例模拟Web服务器: 分析知识点:    浏览器访问网站所看到的页面, 实际是服务器返回的数据, 如何自己做一个网站服务器
    分析:
            浏览器输入网址, 回车: 发送请求 (就是客户端Socket去连接服务端, 并发送数据)
            浏览器显示页面: 是因为服务器返回了页面的代码, 浏览器按照代码显示总结:    补充:    InputStream is = socket.getInputStream();
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader br = new BufferedReader(isr);
    // 合并为一行
    BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    String s = br.readLine();模拟Web服务器: 代码实现10分钟练习: 模拟Web服务器    需求:
    使用ServerSocket实现Web服务器
    具体步骤:
            将web目录赋值粘贴到当前模块中
            创建ServerSocket对象, 监听8080端口
            使用 while(true) 死循环, 在循环中调用ServerSocket对象的 accept() 方法, 获取客户端Socket对象
            在循环中创建线程并 start(), 在线程中传入Runnable的匿名内部类对象
            Runnable匿名内部类中编写读取请求返回页面的代码:
                    1. 通过客户端socket获取InputStream, 经过转换流传递给BufferedReader, 便于读取一行字符串
                    BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    2. 使用BufferedReader只读一行字符串即可, 然后按照空格切割字符串, 获取数组1索引的内容, 然后从1索引截取字符串到末尾
                            即: GET /day11/web/index.html HTTP/1.1 获取其中的 day11/web/index.html
                    3. 创建FileInputStream指向截取出来的字符串作为文件路径
                    4. 通过客户端socket对象获取OutputStream, 先写入以下内容:
                            OutputStream os = socket.getOutputStream();
                            os.write("HTTP/1.1 200 OK\r\n".getBytes());
                            os.write("Content-Type: text/html\r\n".getBytes());
                            os.write("\r\n".getBytes());
                    5. 然后使用一次读取一个byte[]数组方式, 通过刚才创建的FileInputStream对象和socket获取的OutputStream对象, 边读文件边写回客户端
                    6. 关闭FileInputStream和socket, 释放资源代码:    // 模拟Web服务器
   
[Java] 纯文本查看 复制代码
 public class WebServer {
        public static void main(String[] args) throws IOException {
            // 创建服务端ServerSocket
            ServerSocket serverSocket = new ServerSocket(8080);
            System.out.println("Web服务器已启动...");
   
            // 循环接收浏览器请求
            while (true) {
                Socket clientSocket = serverSocket.accept();
   
                // 在子线程中来读取请求的文件返回给浏览器
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            // 先获取网络字节输入流, 用来读取浏览器的请求
                            InputStream is = clientSocket.getInputStream();
                            // 将网络字节输入流转换为缓冲字符输入流, 便于读取一样字符串
                            BufferedReader br = new BufferedReader(new InputStreamReader(is));
                            // 读取一行字符串
                            String line = br.readLine();
                            // 按照空格切割
                            String[] arr = line.split(" ");
                            // 获取中间的元素, 并去掉开头的/  得到html文件的路径
                            String htmlPath = arr[1].substring(1);
                            // 创建文件字节输入流, 用于读取html文件内容
                            FileInputStream fis = new FileInputStream(htmlPath);
                            // 获取网络字节输出流, 用于向浏览器回写文件内容
                            OutputStream os = clientSocket.getOutputStream();
                            // 先回写固定的HTTP响应行和响应头
                            os.write("HTTP/1.1 200 OK\r\n".getBytes());
                            os.write("Content-Type: text/html\r\n".getBytes());
                            os.write("\r\n".getBytes());
                            // 然后再边读边回写文件
                            byte[] bytes = new byte[1024];
                            int len;
                            while ((len = fis.read(bytes)) != -1) {
                                os.write(bytes, 0, len);
                            }
                            // 关流释放资源
                            fis.close();
                            clientSocket.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        }
    }

---今日API    java.net.ServerSocket类: TCP服务端
            // 构造方法
            ServerSocket(int port): 创建一个TCP服务端, 并监听指定端口
            // 成员方法
            Socket accept(): 监听数据, 会阻塞. 收到数据后返回Socket对象
            void close(): 关闭服务端ServerSocket
    java.net.Socket类: TCP客户端
            // 构造方法
            Socket(String ip, int port): 创建TCP客户端对象
            // 成员方法
            OutputStream getOutputStream(): 获取输出流对象, 用于发送数据
            InputStream getInputStream(): 获取输入流, 用于接收数据
            void shutdownOutput(): 关闭输出流, 告知服务端数据发送完毕
            void close(): 关闭客户端Socket今日目标能够辨别UDP和TCP协议特点    UDP:
            1. 无连接的不可靠协议
            2. 以包发送, 一个包64K
            3. 速度快效率高, 容易丢包
    TCP:
            1. 需要建立连接的可靠协议
            2. 没有数据大小限制
            3. 速度慢效率低, 安全性高能够说出TCP协议下两个常用类名称    客户端: Socket
    服务端: ServerSocket能够编写TCP协议下字符串数据传输程序    你好服务器  收到谢谢
   
   

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马