• 13、网络编程


    网络编程

    网络通讯:

      1、找到对方,通过IP地址

      2、数组要发送到对方指定的应用程序上,为了辨识这些应用程序,所以给这些网络应用程序都用数字进行标识,为了方便称呼这个数字,叫做端口(逻辑端口)。

      3、定义通讯规则,这个通讯规则称为协议

        国际组织定义了一个通用的协议TCP/IP。

        特殊IP地址:127.0.0.1本机回返地址

        一般把0~1024的端口数留给系统使用。

     

    三要素:IP,端口,协议

      1、IP地址:InetAddress类

        a) 网络中设备的标识

        b) 不易记忆,可用主机名

        c) 本机回环地址:127.0.0.1 主机名:localhost

     

      2、端口号

        a) 用于标识进程的逻辑地址,不同进程的标识

        b) 有效端口:0~65535,其中0~1024系统使用或保留端口

     

      3、传输协议

        a) 通讯的规则

        b) 常见协议:TCP,UDP

      

    InetAddress类

      该类表示互联网协议(IP)地址

      重要方法:

        Static InetAddress getLocalHost()返回本机

        String getHostAddress()返回IP地址字符串

        String getHostName()获取此IP地址的主机名

        Static InetAddress getByName(String host)该方法可以在给定主机名的情况下确定主机的IP地址。

        Static InetAddress[] getAllByName(String host)在给定主机名的情况下,根据系统上配置的名称服务返回其IP地址所组成的数组。

     

    传输协议

      1、UDP:

        a) 将数据及源和目的封装成数据包中,不需要建立连接

        b) 每个数据报的大小限制在64k内

        c) 因无连接,是不可靠协议

        d) 不需要建立连接,速度快

        例子:邮政邮递邮件的例子

        聊天软件的例子

        网络视频 

     

      2、TCP

        a) 建立连接,形成传输数据的通道

        b) 在连接中进行大数量的传输

        c) 通过三次握手完成连接,是可靠协议

        d) 必须建立连接,效率会稍低

        例子:相当于打电话

         下载的例子

     

    Socket

      1、Socket就是为网络服务提供的一种机制

      2、通信的两端都有Socket

      3、网络通信其实就是Socket间的通信

      4、数据在两个Socket间通过IO传输

     

    UDP传输:

      1、DatagramSocket与DatagramPacket

      2、建立发送端与接收端

      3、建立数据包

      4、调用Socket的发送接收方法

      5、关闭Socket

      发送端和接收端是两个独立的运行程序

     

      DataGramSocket类

        此类表示用来发生和接收数据报包的套接字

        有发送和接收方法:

          Void receive(DatagramPacket p)从此套接字接收数据报包

          Void send(DatagramPacket p)从此套接字发送数据报包

          Socket:套接字

          Receive:收到,接收

          Send:发送

     

      DatagramPacket类

        此类表示数据报包

        Packet:数据包

        UDP传输代码示例:重点是理解传输的步骤

    /**
    
     * 需求:定义一个应用程序,用于接收UDP协议传输的数据并处理
    
     * 定义UDP的接收端:
    
     * 思路:
    
     *   1、定义UDPSocket服务,通常会监听一个端口,其实就是给这个接收网络应用程序定义数据标识。
    
     *     方便于明确哪些数据过来,该应用程序可以处理
    
     *   2、定义一个数包,因为要存储接收的字节数据,因为包对象中有更多功能可以提取字节数据中的不同数据信息
    
     *   3、通过Socket服务的receive方法将收到的数据存入到已定义好的数据包中
    
     *   4、通过数据包对象的特有功能将这些不同的数据取出,打印在控制台上
    
     *   5、关闭资源
    
     *
    
     */
    
    public class UDPReceive {
    
    
      public static void main(String[] args) {
    
        udpReceive();
    
      }
    
      /**
    
       * 该方法用于UDP的数据接收
    
       */
    
      public static void udpReceive(){
    
        DatagramSocket ds = null;
    
        try {
    
          //1、创建UDP,服务,通过DatagramSocket对象
    
          //要记住标识接收的端口,若不然不能接收数据
    
          ds = new DatagramSocket(10000);
    
    
          //2、创建数据包,用于接收发送过来的字节数据
    
          byte[] buf = new byte[65536];
    
          DatagramPacket dp = new DatagramPacket(buf,buf.length);
    
     
          //3、接收发送过来的信息,通过receive方法
    
          ds.receive(dp);
    
     
          //4、通过数据包中方法,将这些数据取出打印在控制台
    
          System.out.println(dp.getAddress().getHostAddress());
    
          System.out.println(new String(dp.getData(),0,dp.getLength()));
    
          System.out.println(dp.getPort());
    
        } catch (Exception e) {
    
          throw new RuntimeException(e.toString());
    
        } finally {
    
          try {
    
            if(ds!=null){
    
              ds.close();
    
            }
    
          } catch (Exception e2) {
            throw new RuntimeException(e2.toString());
    
          }
    
        }
    
      }
    
    }
    /** * 需求: * 通过UDP传输方式,将一段文字数据发送出去 * 定义了一个UDP的发送端 * 思路: *   1、建立UDPSocket服务 *   2、提供数据,并将数据封装到数据包中 *   3、通过Socket服务的发送功能将数包发出去 *   4、关闭资源 * */ public class UDPSend {   public static void main(String[] args) {     udpSend();   }   /**    * 该方法用于UDP的数据发送    */   private static void udpSend() {     DatagramSocket ds = null;     try {       //1、创建UDP服务,通过DatagramSocket对象       ds = new DatagramSocket();       //2、确定数据,并封装成数据包       byte[] buf = "UDP 哥们来了!".getBytes();       DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.145"),10000);       //3、通过Socket服务,将已有的数据包发送出去。通过send方法       ds.send(dp);     } catch (IOException e) {       throw new RuntimeException(e.toString());     } finally {       try {         if(ds!=null){           //4、关闭资源           ds.close();         }       } catch (Exception e2) {         throw new RuntimeException(e2.toString());       }     }   } }

     

    用UDP传输协议制作的聊天小软件

    代码示例:

    /**
    
     * 聊天软件的接收
    
     * @author xiuyuan
    
     *
    
     */
    
    public class UDPReceive_3 implements Runnable{
    
      private DatagramSocket ds;
     
    
      public UDPReceive_3(DatagramSocket ds){
    
        this.ds = ds;
    
      }
      
    
      public void run(){
    
        try {
    
          while(true){
    
            //将接收的数据读取到数包中
    
            byte[] buf = new byte[65536];
    
            DatagramPacket dp = new DatagramPacket(buf,buf.length);
    
    
            ds.receive(dp);
    
     
    
            //获取数据包中的信息
    
            String id = dp.getAddress().getHostAddress();
    
            String data = new String(dp.getData(),0,dp.getLength());
    
     
    
            //将获取的信息打印到控制台
    
            System.out.println(id+":"+data);
    
          }
    
        } catch (Exception e) {
    
          throw new RuntimeException(e.toString());
    
        }
    
      }
    
    }
    
     
    
    /**
    
     * 聊天软件的发送端
    
     * @author xiuyuan
    
     *
    
     */
    
    public class UDPSend_3 implements Runnable{
    
      private DatagramSocket ds;
    
     
    
      public  UDPSend_3(DatagramSocket ds){
    
        this.ds = ds;
      
      }
    
     
    
      public void run(){
    
        BufferedReader bufr = null;
    
        try {
    
          //读取键盘录入信息
    
          bufr = new BufferedReader(new InputStreamReader(System.in));
    
          String line = null;
    
          while((line = bufr.readLine())!=null){
    
            //键盘录入接收标记
    
            if("886".equals(line)){
    
              break;
    
            }
    
     
            //创建数据包,用来封装数据
    
            byte[] buf = line.getBytes();
    
            DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.145"),10002);
    
            //将数据包中的信息发送出去
    
            ds.send(dp);
    
          }
    
        } catch (Exception e) {
    
          throw new RuntimeException(e.toString());
    
        } finally {
    
          try {
    
            if(bufr!=null){
    
              bufr.close();
    
            }
    
          } catch (Exception e2) {
    
            throw new RuntimeException(e2.toString());
    
          }
    
        }
    
      }
    
    }
    
     
    
    /**
    
     *需求:模拟聊天软件通信
    
     * @author xiuyuan
    
     *
    
     */
    
    public class UDPTest {
    
      public static void main(String[] args) {
    
        try {
    
          new Thread(new UDPReceive_3(new DatagramSocket(10002))).start();
    
          new Thread(new UDPSend_3(new DatagramSocket())).start();
    
        } catch (Exception e) {
    
          throw new RuntimeException(e.toString());
    
        }
    
      }
    }

      

    TCP传输

      1、Socket和ServerSocket

      2、建立客户端和服务器端

      3、建立连接后,通过Socket中的IO流进行数据的传输

      4、关闭Socket

      客户端与服务器端是两个独立的应用程序

     

      演示tcp传输

        1、tcp分客户端和服务器端

        2、客户端对应的对象是Socket

           服务器端对应的对象是ServerSocket

     

      需求:用客户端向服务端发送文本信息

        客户端:

          通过查阅Socket对象,发现在该对象在建立时,就可以去连接指定的主机。因为tcp是面向连接的,所以在建立Socket服务时就要有服务端存在并连接成功,形成通路后在该通道进行数据的传输。

          步骤:

            1、创建Socket服务,并指定要连接的主机和端口

     

    Socket类

      此类实现了客户端套接字,套接字是两台机器间通信的端点。

      方法:

        getInputStream()可以获得Socket对象的输入流

        getOutputStream可以获得Socket对象的输出流

        getInetAddress()方法可以获得InetAddress对象,通过该对象getHostAddress()返回获得IP地址

     

      服务器端:

        1、建立服务器端的Socket服务,通过ServerSocket()建立。并监听一个端口

        2、获取连接过来的客户端对象,通过ServerSocket的accept方法获取。没有连接就会等,所以这个方法是阻塞式的,

        3、客户端如果发过来数据,俺们服务器端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发送过来的数据,并打印在控制台

        4、关闭服务端。(可选操作)

     

    ServerSocket类

      此类实现服务器套接字。

      方法accept()可以获取访问服务器的客户端对象Socket对象

     

     

    需求:客户端给服务端发送数据,服务端收到后,给客户端反馈信息

      客户端:

        1、建立Socket服务,指定要连接的主机和端口

        2、获取Socket流中的输出流,将数据写到该流中。通过网络发送给服务端

        3、获取Socket流中的输入流,将服务端反馈的数据获得到,并打印

        4、关闭客户端资源

     

    练习:

      需求:建立一个文本转换服务器,客户端给服务端发送文本数据,服务端会将文本转成大写后再返回给客户端,而且客户端可以不断的发送文本数据,当客户端输入over时,转换结束

      该例出现的问题:数据发送过去,但对方没有接受到,一个原因是数据根本没有发送出去,原因是发送时使用了缓冲区,但没有刷新,数据还在缓冲区中。

      还有就是数据已经发送过去,但没有明确结束标记,对方一直在等待数据,造成不能通信。

     

     

    TCP通信,上传图片

      注意问题:

        1、客户端写数据给服务端,写完后必须给服务端一个结束标记,若不然会使服务端一直处于读取客户端发送过来的数据,操作阻塞,不能给客户端发送反馈信息,客户端也在等待。

          解决该问题的方法,就是给服务端发送结束标记:shudownOutput(),该方法为禁用套接字的输出流,对应TCP套接字,任何以前写入的数据都将被发送,并且后跟TCP的正常连接终止序列。如果在套接字上调用shutdownOutput()后写入套接字输出流,则该流将抛出IOException异常

     

      客户端并发上传的问题:

        服务端:当A客户端连接上以后,被服务端获取到,服务端执行具体执行流程。这时,B客户端连接,只有等待,因为服务端还没有处理完A客户端的请求,还没有循环回来执行accept方法,所以暂时获取不到B客户端对象,为了可以让多个客户端同时并发访问服务端,服务端最好就是将每个客户端封装到一个单独的线程中,这样就可以同时处理多个客户端请求

     

      如何定义线程呢?

        只有明确了每一个客户端要在服务端执行的代码即可,将该代码存入run方法中,

        服务器必须都是多线程的

      服务器原理:服务器都是多线程的,创建一个类,继承Runnable接口,覆盖run方法,并且必须将服务器接收都的客户端对象传入该类中,run方法里面封装了服务器对客户端的处理方法。

     

     

      浏览器访问服务器端时,会按规则向服务器端发送请求消息头

     

     

    URL同一资源定位符,它是指向互联网“资源”的指针。资源可以说是简单的文件或目录,也可以是更为复杂的对象的引用,

      常用方法:

        String getFile(); 获取此URL的文件名

        String getHost(); 获取此URL的主机名

        String getProtocol(); 获取此URL的协议名称

        Int getPort(); 获取此URL的端口号

        String getPath(); 获取此URL的路径部分

        String getQuery(); 获取此URL的查询部分

     

     

      URLConnection openConnection();返回一个URLConnection对象,它表示到URL所引用的远程对象的连接。

     

    URLConnection类

      抽象类URLConnection是所有类的超类,它代表应用程序和URL之间的通信链接。

      通过该类下的方法getInputStream()可以获得从此打开的连接读取的输入流

     

    域名解析:

      DNS:将主机名翻译成IP地址

        访问服务器时,为了方便记忆,不会直接写ip地址,而是写访问的主机名,然后通过DNS域名解析翻译成对应的ip地址返还给浏览器,浏览器在根据ip地址访问对应的主机。

        DNS会先走本机的配置表,找到对象的解析,如果本机没有,采用会访问公网的。

        电脑没有设置DNS时,会自动默认寻找附近的DNS进行解析

     

     

    网络架构:

      1、C/S client/server

        特点:

          该结构的软件,客户端和服务端都需要编写。

          开发成本较高,维护较为麻烦。

     

        好处:

          客户端在本地可以分担一部分运算。

      

      2、B/S browser/server

        特点:

          该结构的软件,只开发服务器端,不开发客户端,因为客户端直接由浏览器取代

          开发成本相对低,维护更为简单。

     

        缺点:

          所有运算都要在服务端完成。

  • 相关阅读:
    linux: system calls(系统调用)(rockylinux8.5)
    学习思考:学习模式探究之案例
    cpp:函数返回数组
    shell: list_executable_file 列出当前文件夹的可执行文件名称(linux)
    c_cpp:多级指针
    哲学思考:人类的逻辑
    学习:对学习的深度思考
    Mounting Kubernetes config map as single file returns error: "caused: mount through procfd: not a directory: unknown"
    查看dockerd日志
    kuberneters 实例 CrashLoopBackOff 排查
  • 原文地址:https://www.cnblogs.com/zyh-blog/p/3259054.html
Copyright © 2020-2023  润新知