网络编程基础知识

  • 先来思考两个问题( 在这里先不解决 )
    • 如何准确的找到一台 或 多台主机?
    • 找到之后如何进行通讯?
  • 网络编程中的几个要素

    • IP 和 端口号
    • 网络通讯协议:TCP / UDP
  • 最后一句话

    • 万物皆对象

1、IP介绍——英文:inetAdress——IP地址

  • 作用:标记网络中每台计算机的身份,网络中每台计算机都有一个唯一的身份号码,就和人的身份证一样

    • 举个例子:如127.0.0.1——指:本机地址( localhost )
  • IP的表示方法

    • ipv4 / ipv6

      • ipv4:由一个4字节32位的整数构成( 如:192.168.100.1 ),每8位用0 ~ 255表示( 即:例子中的每一个数字不超过255 ),它们彼此之间用  " . " 隔开,所以这个ipv4能够表示42亿多个ip地址。但是有30多亿在北美,而亚洲只有4亿多点,而人这么多,所以这种表示方式根本不够用,因此:在2011年的时候这些ip地址就已经用完了——————咋个办?所以弄出了ipv6
      • ipv6:有一个16字节128位的整数构成( 如:Y.Y.Y.Y.Y.Y.Y.Y ),每段的范围是0 ~ 65535
  • IP分类

    • 公网( 互联网) 、 私网( 局域网 )————直接看图

      • 其中,不想详细了解的话,作为程序员只需要知道两个命令即可——ipconfig 和 ping
        • ipconfig:是查看自己的计算机ip地址————即:在dos窗口中输入这个命令回车即可看到
        • ping:是查看自己的计算机是否链接上知道ip地址的计算机————即:ping 接要查看的计算机ip地址
  • 在java中怎么玩儿ip?

    • 多提一句:java中和网络相关的都在java.net包下
    • java中已经封装好了一个类————inetAdress类:这个类没有构造方法,所以不能new对象,直接通过 类名. 调用方法( 方法也不多,就下图中的这几个,而且也没多大用 )


      • // 1、获取ip名字————参数是String host
        System.out.println( InetAddress.getByName("127.0.0.1") ); System.out.println( InetAddress.getByName("www.baidu.com") ); // 这个没啥好玩的

        效果如下:

2、端口

  • 先来思考一个问题

    • 一台计算机它是怎么读取数据的?————换句话说:它是怎么知道一个 / 一些数据是哪个软件发过来的?( 接收的时候对数据进行处理嘛 )
  • 为了解决上述的问题————端口就来了

    • 端口:指的是计算机上一个程序的进程
    • 端口的范围: 0 ~ 65535
    • 不同的应用程序,端口都不一样,这样就可以通过固定的端口进行收发数据了
  • 常见的默认端口如下

    • MySQL ————>  3306

      Tomcat ————> 8080

      HTTP ————>  80

      SSH ————> 22 这是linux下的安全传输协议端口

      FTP ————> 21

    • 多一点了解的话,就看下图
  • 在java中怎么玩端口?————也是封装好了的,使用一个类InetSocketAddress————也没什么好玩的

3、通信协议——这才是重点

  • 协议:就是一种约定嘛,就好比————我们说的普通话
  • 网络通信协议:也就是网络之间进行通讯的约定嘛————管速率、传输码率、传输控制............
  • 由网络通信协议看出:麻不麻烦?

    • 当然麻烦涩,大事化小咯————分层,如下图所示

    • 看起来好多啊,但是没事儿,又不是专门搞网络的,所以不需要整那么多,就几个而已
  • 1、TCP / UDP协议

    • TCP:传输控制层协议( 用户传输协议 )
      • 特点:

        • 面向连接式协议:指 应用程序在使用TCP协议之前必须先建立TCP连接,在传送数据完毕后必须释放已经建立的TCP连接
        • 每一条TCP连接只能有两个端点,即:A和B连接,A就不能再用TCP和其他的连接在一起 ( 点对点连接嘛 )
        • TCP可靠,即:通过TCP连接传送的数据,无差错、不丢失、不重复、并且按序到达
        • 提供全双工通信:即:TCP允许通信双方( 断开不行啊 )的应用进程在任何时候都能发送数据
        • 面向字节流传输:即:传输的数据是字节流,关注点是:字节。什么意思?
          • 假如:两个端点之间传输了一句话,但是这句话在TCP里面不是文字,而是这句话的每个字符对应的字节数字,如:a ———> 97
    • 在这里需要了解两个东西:三次握手、四次挥手(四次分手)

      • 先看这两个的图

        • 三次握手


        • 四次挥手( 四次分手 )


        • 三次握手到底是什么意思?

          • 如上图

            • A:你瞅啥? ————> 客户端发送连接的请求,服务端对这个请求进行监听
            • B:瞅你咋地 ————> 然后服务端回应客户端: 可以 / 不可以 进行传输
            • A、B:走,干一架 ————> 最后客户端 进行 / 不进行 数据传输
        • 那四次挥手又到底是个啥子玩意儿?

          • 不是备注了一下:四次分手吗,那就用分手来理解一下

            • 男:我想跟你分手 ————> 客户端向服务端发送连接的请求
            • 女:你要分手?—————> 服务端响应客服端
            • 女:你真的要分手??? ————> 服务端询问客户端是否准备链接
            • 男:老子确定分手 ————> 服务端 和 客户端建立连接
    • UDP:用户数据报协议

      • 特点:

        • 面向无连接式协议:即:发送数据之前不需要建立连接
        • UDP不可靠(不稳定):即:数据的传输中只是尽最大努力把数据送达,不保证一点不丢失( 如:停电了、断网了 ,哦豁 ~ 数据没穿得过去 )
        • 支持一对一、一对多、多对多通信
    • TCP和UDP的对比

      • TCP( 好比:打电话 )

        • 安全、可靠
        • 连接稳定( 三次握手、四次挥手 )
        • 客户端 和 服务端界限明确
        • 缺点:要等传输完成,才能释放连接,效率低
      • UDP( 好比:发短信、写信 )
        • 不稳定、不靠谱
        • 客户端 和 服务端界限不明确
        • 不管有没有准备好,都可以发给你( 就好比:导弹,想整你的时候,还需要管你准没准备好吗 )
        • 漏洞就来了

          • 黑别人的时候,发布洪水攻击( 即:疯狂发送东西,看好的还是坏的信息啊 )————最后:直接把别人网络干趴
  •  2、TCP协议编程———即:Socket编程

    • Socket就相当于是 服务端 和 客户端 之间的那个连接通道

    • 服务器端使用ServerSocket套接字 并绑定监听端口
    • 服务端 阻塞等待连接
    • 客户端使用 Socket 并指定服务端IP 和 端口
      • 服务端
        • //1. 服务器端套接字
          ServerSocket server = new ServerSocket(8848);
          //2. 监听客户端连接
          Socket socket = server.accept(); 
      • 客户端

        • //1. 创建客户端套接字
          Socket socket = new Socket( "127.0.0.1" , 8848);
    • 实操一手儿  

      • 1、客户端 给 服务端 发送数据

        • package cn.xieGongZi.test;
          
          import java.io.BufferedReader;
          import java.io.IOException;
          import java.io.InputStreamReader;
          import java.net.ServerSocket;
          import java.net.Socket; // 服务端
          public class Server { public static void main(String[] args) { Socket socket = null;
          BufferedReader br = null; // 1、需要建立一个连接的通道sorket————即:套接字
          try { ServerSocket serverSocket = new ServerSocket(9999);// 需要一个端口号————即:这个链接通道的名字是什么
          // 这个东西就是底层中封装的3次握手 // 2、有了这个通道之后就可以等着客户端来链接了——————使用accept()方法
          System.out.println("正在等待链接:");
          socket = serverSocket.accept(); // 等待客户端的链接————客户端和服务端真正建立了连接通道 // 3、如果客户端链接上就可以进行文件的 读 / 写了
          // 读取文件————这里是传输的文字,所以直接一行一行的读取,快一点嘛
          br = new BufferedReader( new InputStreamReader( socket.getInputStream() ) ); String buffer;
          while ( ( buffer = br.readLine() ) != null ){
          System.out.println("服务端收到了:" + buffer );
          } } catch (IOException e) {
          e.printStackTrace();
          }finally { // 最后关闭流管道和网络链接通道————但是Socket 和 流管道 是在try中,这里拿不到,所以:提升作用域————全局变量
          // 倒着关闭
          if ( socket != null ){
          try {
          socket.close();
          } catch (IOException e) {
          e.printStackTrace();
          }
          } if ( br != null ){
          try {
          br.close();
          } catch (IOException e) {
          e.printStackTrace();
          }
          } }
          }
          }
        • package cn.xieGongZi.test;
          
          import java.io.BufferedWriter;
          import java.io.IOException;
          import java.io.OutputStreamWriter;
          import java.net.Socket; // 客户端
          public class Client { public static void main(String[] args) { Socket clientSocket = null;
          BufferedWriter bw = null; // 1、建立链接通道————需要ip和端口号
          try {
          clientSocket = new Socket("127.0.0.1", 9999); // 2、开始传输文件————建立流管道
          bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
          bw.write("不球晓得传输个啥子东西"); } catch (IOException e) {
          e.printStackTrace();
          }finally { // 关闭流管道 和 网络链接通道
          if ( bw != null ){
          try {
          bw.close();
          } catch (IOException e) {
          e.printStackTrace();
          }
          } if ( clientSocket != null ){
          try {
          clientSocket.close();
          } catch (IOException e) {
          e.printStackTrace();
          }
          }
          }
          }
          }
        • 效果如下:
      • 2、多个客户端 给 服务端发送数据

        • package cn.xieGongZi.testManyClientToServer;
          
          import java.io.BufferedReader;
          import java.io.IOException;
          import java.io.InputStreamReader;
          import java.net.ServerSocket;
          import java.net.Socket; // 服务端————可以让多个客户端来进行链接
          public class Server { public static void main(String[] args) { // 1、建立链接通道
          try {
          ServerSocket serverSocket = new ServerSocket(2020); while ( true ){ // 保证服务端能够多开,不然只开启一个准备链接通道,那多个客户端链接只能链接第一个了 // 2、等待客户端来链接
          System.out.println("等待连接");
          Socket socket = serverSocket.accept(); // 3、但是:如果在这里直接进行数据的读写,那又不行
          // 因为:万一第一个链接通道一致没有客户端传输数据过来,那不就堵着了吗
          // 所以:开线程————让每一个客户端 和 服务端进行链接之后都去单独的一个线程中进行读写数据
          // 开线程
          new openThread(socket).start();
          } } catch (IOException e) {
          e.printStackTrace();
          }
          }
          } // 开线程
          class openThread extends Thread{ private Socket socket; public openThread( Socket socket ){
          this.socket = socket;
          } @Override
          public void run() { // 这个线程里面要干的事情:就是让服务端 和 客户端进行数据读写
          // 但是:问题来了
          // 怎么能够保证是哪一个连接通道进行读写数据?
          // 所以:需要把链接通道传进来————组合的方式 // 客户端 和 服务端 的链接通道正式开始进行读写数据
          BufferedReader br = null;
          try { br = new BufferedReader(new InputStreamReader(socket.getInputStream())); String data;
          while ( ( data = br.readLine() ) != null ){
          System.out.println(data);
          }
          } catch (IOException e) {
          e.printStackTrace();
          }finally { if ( br != null ){
          try {
          br.close();
          } catch (IOException e) {
          e.printStackTrace();
          }
          } if ( socket != null ){
          try {
          socket.close();
          } catch (IOException e) {
          e.printStackTrace();
          }
          }
          }
          }
          }
        • package cn.xieGongZi.testManyClientToServer;
          
          import java.io.BufferedWriter;
          import java.io.IOException;
          import java.io.OutputStreamWriter;
          import java.net.Socket; // 客户端
          public class Client { public static void main(String[] args) { Socket clientSocket = null;
          BufferedWriter bw = null; // 1、建立链接通道————需要ip和端口号
          try {
          clientSocket = new Socket("127.0.0.1", 2020); // 2、开始传输文件————建立流管道
          bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
          bw.write("不球晓得传输个啥子东西"); } catch (IOException e) {
          e.printStackTrace();
          }finally { // 关闭流管道 和 网络链接通道
          if ( bw != null ){
          try {
          bw.close();
          } catch (IOException e) {
          e.printStackTrace();
          }
          } if ( clientSocket != null ){
          try {
          clientSocket.close();
          } catch (IOException e) {
          e.printStackTrace();
          }
          }
          }
          }
          }
      • 3、客户端给客户端发送数据( 即:多人聊天 )————注意:直接通过客户端 和 客户端交互是不可以的

        • package cn.xieGongZi.clientToClient;
          
          import java.io.BufferedReader;
          import java.io.IOException;
          import java.io.InputStreamReader;
          import java.io.PrintWriter;
          import java.net.ServerSocket;
          import java.net.Socket;
          import java.util.ArrayList;
          import java.util.List; // 服务端————玩儿客户端 与 客户端进行聊天
          public class Server { static List<Socket> socketList= new ArrayList<>(); public static void main(String[] args) { ServerSocket serverSocket = null; // 1、建立通信管道链接
          try {
          serverSocket = new ServerSocket(3030); // 2、等待客户端来链接
          System.out.println("正在等待链接:");
          Socket acceptSocket = serverSocket.accept(); // 3、如果客户端链接上了,则:进行数据的读写
          // 读取客户端的数据————照样的放在这里不好,应该单独让它们去一下线程里做事
          // 所以:开线程
          new openServerThread(acceptSocket).start(); // 最后搞一件事情————把从客户端接过来的链接通道这个客人给我放到集合中去
          Server.socketList.add(acceptSocket);

          } catch (IOException e) {
          e.printStackTrace();
          }finally { if (serverSocket != null ){
          try {
          serverSocket.close();
          } catch (IOException e) {
          e.printStackTrace();
          }
          }
          }
          }
          }


          // 开线程
          class openServerThread extends Thread{ // 一样的保证:客户端 与 客户端在一个连接通道中————还是用组合
          private Socket socket;
          public openServerThread( Socket socket ){
          this.socket = socket;
          } // 线程该做的事
          @Override
          public void run() { BufferedReader br = null; // 读取客户端的数据
          try {
          br = new BufferedReader(new InputStreamReader(socket.getInputStream())); String data;
          while ( ( data = br.readLine() ) != null ){ // 在这里:服务端就接收到了客户端的数据
          // 但是:要搞得事情不是把这个数据给打印出来看效果
          // 而是:在这里借服务端的手,把客户端传过来的数据 转发 给其他客户端
          // 可:问题又来了————服务端只是从客户端哪里接客了,但是接了哪些客,它不知道
          // 因此:需要一个东西来记录一下————服务端接了哪些客————集合(因为:具体多少个客户端不知道)
          // 所以:定义一个全局的集合
          // 然后:服务端接一个客户端,那就把这个客户端放到集合中去 // 最后需要搞一件事情涩————就是去集合中找除了自己这个客户端以外的其他客户端(即:另外的Socket通道)
          // 然后把接收过来的数据 转发 给其他客户端
          for (int i = 0; i < Server.socketList.size(); i++) { // 遍历这个集合
          Socket checkSocket = Server.socketList.get(i); // 看遍历出来的这个Socket是不是它自己本身————是的话就不转发了
          if ( this.socket == checkSocket ) continue; // 否则:就是其他的Socket通道嘛————即:其他的客户端————那就转发数据( 输出数据嘛 )
          new PrintWriter( checkSocket.getOutputStream() ).println(data); }
          }
          } catch (IOException e) {
          e.printStackTrace();
          }finally { if ( br != null ){ try {
          br.close();
          } catch (IOException e) {
          e.printStackTrace();
          }
          } }
          }
          }
        • package cn.xieGongZi.clientToClient;
          
          import java.io.BufferedWriter;
          import java.io.IOException;
          import java.io.OutputStreamWriter;
          import java.net.Socket;
          import java.util.Scanner; // 客服端
          public class Client { public static void main(String[] args) { try {
          Socket clientSocket = new Socket("127.0.0.1", 3030); // 这里问题又来了,实现客户端 与 客户端 聊天嘛。所以传输的东西肯定不能写死啊
          // 因此:再开线程
          new openClientThread(clientSocket).start(); } catch (IOException e) {
          e.printStackTrace();
          } }
          }


          // 开线程
          class openClientThread extends Thread{ private Socket socket; public openClientThread( Socket socket ){
          this.socket = socket;
          } @Override
          public void run() { // 线程该做的事
          System.out.println("聊天开始");
          Scanner input = new Scanner(System.in); // 进行数据传送
          while (true){ try {
          BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); String text = input.nextLine();
          bw.write(text);
          } catch (IOException e) {
          e.printStackTrace();
          }
          }
          }
  • 3、UDP协议编程———即:DatagramSocket编程

    • UDP编程————其实和TCP一样,玩法都一样,只是Socket变成了DatagramSocket而已

      • 不需要连接,但是需要知道对方的地址
      • 没有客户端 和 服务端的概念————可以互相发
      • 就像:发包裹一样————只需要知道地址就可以了
    • 直接上实例 

      • package AboutUDP.SendFiles;
        
        import java.net.DatagramPacket;
        import java.net.DatagramSocket;
        import java.net.InetAddress; public class SendFile {
        public static void main(String[] args) throws Exception {
        //1、和传文件的对象建立链接--->
        // 这个socket和Receive里的socket是同一个:起到链接的作用
        DatagramSocket socket = new DatagramSocket(); //2、需要知道接收端的ip和端口号
        InetAddress ip = InetAddress.getByName("localhost");
        int port = 8888; //3、得有一个要发送的东西--->可以通过写程序让它去网上下东西,然后发过去
        //在这里 用自定义一个内容发过去测试
        String data= "你像个傻逼,还不晓得努力!"; //4、发什么内容,发的内容是从哪里开始---结束,发给什么Ip和端口
        DatagramPacket packet = new DatagramPacket(data.getBytes(),0,data.getBytes().length,ip,port);
        //data.getBytes()把要传送的数据包转为字节型数组:是因为电脑底层的传送实质是以字节来传送的 //5、发送文件
        socket.send(packet); //6、关闭链接
        socket.close();
        }
        }
      • package AboutUDP.SendFiles;
        
        import java.net.DatagramPacket;
        import java.net.DatagramSocket; public class ReceiveFile {
        public static void main(String[] args) throws Exception {
        //1、得有一个端口来让别人链接
        DatagramSocket socket = new DatagramSocket(8888); //2、接收包文件
        byte[] receiveFile = new byte[1024];//这个空的数据包是用来接收数据的:把接收的数据装在这里面
        //DatagramPacket这才是接收数据的命令
        DatagramPacket packet = new DatagramPacket(receiveFile,0,receiveFile.length); //3、接收 装好的包文件
        socket.receive(packet); //看一下效果
        System.out.println(new String(packet.getData(),0,packet.getLength()));
        //4、关闭链接--->实质为关闭端口,防止端口占用
        socket.close();
        }
        }

  • 4、URL
    • 这个就不玩了,这个玩意儿就是定位网上的资源嘛( 怎么定位,就是输入的网址呗 ),因为:这个url就是一个对象,代表的就是url地址,也就是浏览器( 输入网址弹出来的不就是相应的页面内容吗 )
    • 这玩意儿在Java中怎么创建出来?

      • 万物皆对象嘛,这句话在博客开篇不是白说的,因此:new一下就出来了,至于具体怎么玩自行看源码摸索( 提示:这个东西可以搞小爬虫,获取网上资源 )

自此:Java相关的网络编程就整完了

javaSE高级篇3 — 网络编程 — 更新完毕的更多相关文章

  1. javaSE高级篇2 — 流技术 — 更新完毕

    1.先认识一个类----File类 前言:IO相关的一些常识 I / O----输入输出 I     输入     input 0    输出     output I / o 按数据的流动方向来分- ...

  2. python自动化开发-[第八天]-面向对象高级篇与网络编程

    今日概要: 一.面向对象进阶 1.isinstance(obj,cls)和issubclass(sub,super) 2.__setattr__,__getattr__,__delattr__ 3.二 ...

  3. 4 - 基于ELK的ElasticSearch 7.8.x技术整理 - 高级篇( 续 ) - 更新完毕

    0.前言 这里面一些理论和前面的知识点挂钩的,所以:建议看一下另外3篇知识内容 基础篇:https://www.cnblogs.com/xiegongzi/p/15684307.html java操作 ...

  4. 《Java从入门到放弃》JavaSE入门篇:网络编程(入门版)

    要进行网络编程,首先要搞清楚目的是什么. 网络编程说简单点就是在网络上的计算机进行数据的交互. 既然要进行数据交互,那就需要有一个发送方和一个接受方. 按网络上的说法,就是一个攻一个受· 当然,现阶段 ...

  5. javaSE高级篇5 — java8新特性详解———更新完毕

    java8新特性 在前面已经见过一些东西了,但是:挖得有坑儿 1.lambda表达式 lambda表达式是jdk1.8引入的全新语法特性 它支持的是:只有单个抽象方法的函数式接口.什么意思? 就是说: ...

  6. Java入门 - 高级教程 - 05.网络编程

    原文地址:http://www.work100.net/training/java-networking.html 更多教程:光束云 - 免费课程 网络编程 序号 文内章节 视频 1 概述 2 Soc ...

  7. 大数据学习笔记——Java篇之网络编程基础

    Java网络编程学习笔记 1. 网络编程基础知识 1.1 网络分层图 网络分层分为两种模型:OSI模型以及TCP/IP网络模型,前者模型分为7层,是一个理论的,参考的模型:后者为实际应用的模型,具体对 ...

  8. Java之旅_高级教程_网络编程

    摘自:http://www.runoob.com/java/java-networking.html JAVA网络编程 网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来. j ...

  9. 01 语言基础+高级:1-9 网络编程_day11【网络编程】

    day11[网络编程] 主要内容 软件架构CS/BS 网络通信三要素 TCP通信 Socket套接字 ServerSocket 教学目标 能够辨别UDP和TCP协议特点 能够说出TCP协议下两个常用类 ...

随机推荐

  1. STM32中按键中断分析

    在按键学习中,我们有用到查询的方法来判断按键事件是否发生,这种查询按键事件适用于程序工作量较少的情况下,一旦程序中工作量较大较多,则势必影响程序运行的效率,为了简化程序中控制的功能模块的执行时间,引入 ...

  2. 彻底搞通TCP滑动窗口

    在我们当初学习网络编程的时候,都接触过TCP,在TCP中,对于数据传输有各种策略,比如滑动窗口.拥塞窗口机制,又比如慢启动.快速恢复.拥塞避免等.通过本文,我们将了解滑动窗口在TCP中是如何使用的. ...

  3. 全志Tina_dolphin播放音视频裸流(h264,pcm)验证

    最近在验证tina对裸流音视频的支持,主要指h264视频裸流及pcm音频裸流. 在原始sdk中有针对很多video和audio类型的parser,但就是没有找到pcm和h264的parser,所以需要 ...

  4. 文件挂载swap

    根目录使用率超过79%,根目录总共45G,/home目录下有文件6G的swap,在新加的300G分区/OracleDB中建立4个G的swap替代/home下在swap文件 1.创建4个G的空文件 #  ...

  5. uni-app视频组件设置圆角

    无法实现,建议写个image在中间位置加个播放按钮,点击播放跳转新页面只需要在跳转参数里面把视频链接加上,在onLoad里面获取视频链接,自动播放视频,很多app目前都是这样做的,关闭页面后视频会自动 ...

  6. 【CVE-2020-1948】Apache Dubbo Provider反序列化漏洞复现

    一.实验简介 实验所属系列: 系统安全 实验对象:本科/专科信息安全专业 相关课程及专业: 计算机网络 实验时数(学分):2 学时 实验类别: 实践实验类 二.实验目的 Apache Dubbo是一款 ...

  7. Java 源码如何分析?

    如何阅读源码?万事开头难,源码从哪里开始看?我也是刚对源码的阅读研究不深,但是可以谈谈自己的源码阅读感受. 刚开始吧,只是对某些代码的实现原理感到好奇,好奇是怎么实现这种功能,实现这种效果的,对其背后 ...

  8. Integer.valueOf()和Integer.parseInt()区别

    他们返回类型的不同是最大的原因. static int parseInt(String s) 将字符串参数作为有符号的十进制整数进行分析. static Integer valueOf(int i) ...

  9. java eclipse调试提示Source not found 或 一闪而过 解决方法

    Web工程Eclipse  debug方式启动,在断点的位置被成功拦截,但是没有跳转到工程的代码处,提示如下: 当然这个时候如果我继续按F5的话呢,程序又会接着正常运行了.到这里那就是说程序本身是没有 ...

  10. Django笔记&教程 6-3 使用模型(models)创建表单(form)

    Django 自学笔记兼学习教程第6章第3节--使用模型(models)创建表单(form) 点击查看教程总目录 本文参考:Forms for models 1 - 初步介绍 很多时候,我们使用的表单 ...