• Java网络编程


    一、概述

    计算机网络

    • 计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。

    网络编程的目的

    • 传播交流信息,数据交换,通信…

    想要达到这个效果需要什么

    • 如何准确的定位网络上的一台主机?
      • 端口,定位到这个计算机上的某个资源
    • 找到了这个主机,如何传输数据?

    二、网络通信的要素

    如何实现网络的通信

    • 通信双方地址:ip、端口号
    • 规则:网络通信的协议
      • TCP/IP参考模型
        在这里插入图片描述
    • 小结
      • 网络编程中有两个主要的问题
        • 如何准确的定位到网络上的一台或多台主机
        • 找到主机之后如何进行通信
      • 网络编程中的要素
        • IP 和 端口号(IP类)
        • 网络通信协议(TCP、UDP类)
      • 万物皆对象

    三、IP

    ip地址:InetAddress

    • 唯一定位一台网络上的计算机
    • 127.0.0.1:本机 localhost
    • ip地址的分类
      • 通过IP地址分类:IPv4 / IPv6
        • IPv4:如127.0.0.1,由4个字节组成,每个字节的范围是0~255。共有42亿个,30亿都在北美,亚洲只有4亿。2011年就用尽了。
        • IPv6:如2001:0DB8:0000:0023:0008:0800:200C:417A,由8个无符号整数组成。IPv6的地址长度为128位,是IPv4地址长度的4倍。于是IPv4点分十进制格式不再适用,采用十六进制表示。
      • 通过公网(互联网)-私网(局域网)分类
        • ABCD类地址:根据网络的标识长度进行区分,A类为8位、B类为16位、C类为24位、D类为多播地址。
        • 如192.168.xx.xx,专门给组织内部使用的
    • 域名:记忆IP问题
      • IP:www.baidu.com
    //测试IP
    public class TestInetAddress {
        public static void main(String[] args) {
            try {
                //查询本机地址
                InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");
                System.out.println(inetAddress1); ///127.0.0.1
                InetAddress inetAddress2 = InetAddress.getByName("localhost");
                System.out.println(inetAddress2); //localhost/127.0.0.1
                InetAddress inetAddress3 = InetAddress.getLocalHost();
                System.out.println(inetAddress3); //LIANG/192.168.0.105
    
                //查询网站IP地址
                InetAddress inetAddress4 = InetAddress.getByName("www.baidu.com");
                System.out.println(inetAddress4); //www.baidu.com/183.232.231.173
    
                //常用方法
    //            System.out.println(inetAddress4.getAddress());
                System.out.println(inetAddress4.getCanonicalHostName()); //规范的名字
                System.out.println(inetAddress4.getHostAddress()); //ip
                System.out.println(inetAddress4.getHostName()); //域名,或者自己电脑的名字
    
    
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    四、端口

    端口表示计算机上的一个程序的进程

    • 不同的进程有不同的端口号,用来区分软件。
    • 端口号被规定为 0~65535。
    • 分为TCP、UDP,单个协议下端口号不能冲突。
    • 端口分类:
      • 公有端口:0~1023
        • HTTP:80
        • HTTPS:443
        • FTP:21
        • Telent:23
      • 程序注册端口:1024~49151,分配用户或者程序。
        • Tomcat:8080
        • MySQL:3306
        • Oracle:1521
      • 动态、私有端口:49152~65535
        netstat -ano #查看所有的端口
        netstat -ano|findstr "5900" #查看指定的端口
        tasklist|findstr "8696" #查看指定端口的进程
        
        • 1
        • 2
        • 3
        Ctrl + Shift + Esc:打开任务管理器
    • InetSocketAddress类
    public class TestInetSocketAddress {
        public static void main(String[] args) {
            InetSocketAddress inetSocketAddress1 = new InetSocketAddress("127.0.0.1", 8080);
            InetSocketAddress inetSocketAddress2 = new InetSocketAddress("localhost", 8080);
            System.out.println(inetSocketAddress1); // /127.0.0.1:8080
            System.out.println(inetSocketAddress2); // localhost/127.0.0.1:8080
    
            System.out.println(inetSocketAddress1.getAddress()); // /127.0.0.1
            System.out.println(inetSocketAddress1.getHostName()); //地址 127.0.0.1
            System.out.println(inetSocketAddress1.getPort()); //端口 8080
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    五、通信协议

    协议:约定,好比我们现在说的普通话。
    网络通信协议:速率,传输码率,代码结构,传输控制…

    • TCP/IP协议簇:实际上是一组协议
      • 比较重要的协议:
        • TCP:用户传输协议
        • UDP:用户数据报协议
      • 比较出名的协议:
        • TCP:用户传输协议
        • IP:网络互连协议
    • TCP 和 UDP的对比
      • TCP:打电话
        • 连接,稳定
        • 三次握手,四次挥手
          最少需要三次,才能保证稳定的连接。
        • 分为客户端和服务端
        • 传输完成,释放连接,效率低
      • UDP:发短信
        • 不连接,不稳定
        • 也是分为客户端和服务端,但是没有明确的界限
        • 不管有没有准备好,都可以发送
        • DDOS:洪水攻击(饱和攻击)

    六、TCP

    • 客户端
      1. 连接服务器(Socket)
      2. 发送消息
      //客户端
      public class TcpClientDemo01 {
          public static void main(String[] args) {
              Socket socket = null;
              OutputStream os = null;
      
              try {
                  //1. 要知道服务器的地址,端口号
                  InetAddress serverIP = InetAddress.getByName("127.0.0.1");
                  int port = 9999;
                  //2. 创建一个socket连接
                  socket = new Socket(serverIP, port);
                  //3. 发送消息  IO流
                  os = socket.getOutputStream();
                  os.write("你好,欢迎学习狂神说Java".getBytes());
              } catch (Exception e) {
                  e.printStackTrace();
              } finally {
                  if (os != null) {
                      try {
                          os.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
                  if (socket != null) {
                      try {
                          socket.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              }
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
    • 服务器
      1. 建立服务的端口(ServerSocket)
      2. 等待用户的连接(accept)
      3. 接收用户的消息
      //服务端
      public class TcpServerDemo01 {
          public static void main(String[] args) {
              ServerSocket serverSocket = null;
              Socket socket = null;
              InputStream is = null;
              ByteArrayOutputStream baos = null;
      
              try {
                  //1. 要有一个地址
                  serverSocket = new ServerSocket(9999);
      
                  while (true) { //不停地接收消息
                      //2. 等待客户端连接
                      socket = serverSocket.accept();
                      //3. 读取客户端的消息
                      is = socket.getInputStream();
                      //方式一:可能会出现乱码
      //            byte[] buffer = new byte[1024];
      //            int len;
      //            while ((len = is.read(buffer)) != -1) {
      //                String msg = new String(buffer, 0, len);
      //                System.out.println(msg);
      //            }
                      //方式二:
                      baos = new ByteArrayOutputStream();
                      byte[] buffer = new byte[1024];
                      int len;
                      while ((len = is.read(buffer)) != -1) {
                          baos.write(buffer, 0, len);
                      }
                      System.out.println(baos.toString());
                  }
              } catch (IOException e) {
                  e.printStackTrace();
              } finally {
                  //关闭流
                  if (baos != null) {
                      try {
                          baos.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
                  if (is != null) {
                      try {
                          is.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
                  if (socket != null) {
                      try {
                          socket.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
                  if (serverSocket != null) {
                      try {
                          serverSocket.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              }
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68

    文件上传

    • 客户端
    public class TcpServerDemo02 {
        public static void main(String[] args) throws Exception {
            //1. 创建一个Socket连接
            Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
            //2. 创建一个输出流
            OutputStream os = socket.getOutputStream();
            //3. 读取文件
            FileInputStream fis = new FileInputStream(new File("2022.06.25.jpg"));
            //4. 写出文件
            byte[] buffer = new byte[1024];
            int len;
            while ((len = fis.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }
            //通知服务器,已经传输完毕
            socket.shutdownOutput(); //我已经传输完毕
            //确定服务器接收完毕,才能够断开连接
            InputStream is = socket.getInputStream();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer2 = new byte[1024];
            int len2;
            while ((len2 = is.read(buffer2)) != -1) {
                baos.write(buffer2, 0, len2);
            }
            System.out.println(baos.toString());
            //5. 关闭资源
            baos.close();
            is.close();
            fis.close();
            os.close();
            socket.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 服务器端
    public class TcpClientDemo02 {
        public static void main(String[] args) throws Exception {
            //1. 创建一个端口(服务器端)
            ServerSocket serverSocket = new ServerSocket(9000);
            //2. 监听客户端的连接
            Socket socket = serverSocket.accept(); //阻塞式监听,会一直等待客户端连接
            //3. 获取输入流
            InputStream is = socket.getInputStream();
            //4. 文件输出
            FileOutputStream fos = new FileOutputStream(new File("receive.jpg"));
            byte[] buffer = new byte[1024];
            int len;
            while ((len = is.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
            //通知客户端我接收完毕了
            OutputStream os = socket.getOutputStream();
            os.write("我接收完毕了,你可以断开了".getBytes());
            //5. 关闭资源
            os.close();
            fos.close();
            is.close();
            socket.close();
            serverSocket.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    Tomcat

    • 服务器端
      • 自定义 S
      • Tomcat服务器 S:Java后台开发
    • 客户端
      • 自定义 C
      • 浏览器 B

    七、UDP

    发短信:需要知道对方的地址

    • 发送消息
    //不需要连接服务器
    public class UdpClientDemo01 {
        public static void main(String[] args) throws Exception {
            //1. 建立一个Socket
            DatagramSocket socket = new DatagramSocket();
    
            //2. 建个包
            String msg = "你好啊,服务器!";
    
            //发送给谁
            InetAddress localhost = InetAddress.getByName("localhost");
            int port = 9090;
            //5个参数:数据(msg.getBytes()), 数据的长度起始(0, msg.getBytes().length), 要发送给谁(localhost, 9090)
            DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, 9090);
    
            //3. 发送包
            socket.send(packet);
    
            //4. 关闭流
            socket.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 接收端
    //等待客户端的连接
    public class UdpServerDemo01 {
        public static void main(String[] args) throws Exception {
            //开放端口
            DatagramSocket socket = new DatagramSocket(9090);
            //接收数据包
            byte[] buffer = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
    
            socket.receive(packet); //阻塞接收
            System.out.println(packet.getAddress().getHostAddress());
            System.out.println(new String(packet.getData(), 0, packet.getLength()));
            //关闭连接
            socket.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    实现循环发送消息和接收消息

    • 循环发送消息
    public class UdpSenderDemo01 {
        public static void main(String[] args) throws Exception {
    
            DatagramSocket socket = new DatagramSocket(8888);
    
            //准备数据:控制台读取  System.in
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    
            while (true) {
                String data = reader.readLine();
                byte[] datas = data.getBytes();
                DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress("localhost", 6666));
                socket.send(packet);
    
                if (data.equals("bye")) {
                    break;
                }
            }
            reader.close();
            socket.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 循环接收消息
    public class UdpReceiverDemo01 {
        public static void main(String[] args) throws Exception{
    
            DatagramSocket socket = new DatagramSocket(6666);
    
            while (true) {
                //准备接收包裹
                byte[] container = new byte[1024];
                DatagramPacket packet = new DatagramPacket(container, 0, container.length);
                socket.receive(packet); //阻塞式接收包裹
    
                //断开连接  bye
                byte[] data = packet.getData();
                String receiveData = new String(data, 0, data.length);
                System.out.println(receiveData);
    
                if (receiveData.equals("bye")) {
                    break;
                }
            }
            socket.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在线咨询(双方都可以是发送方,也可以是接收方)

    • 发送类
    public class TalkSend implements Runnable{
        DatagramSocket socket = null;
        BufferedReader reader = null;
    
        private int fromPort;
        private String toIP;
        private int toPort;
    
        public TalkSend(int fromPort, String toIP, int toPort) {
            this.fromPort = fromPort;
            this.toIP = toIP;
            this.toPort = toPort;
    
            try {
                socket = new DatagramSocket(fromPort);
                reader = new BufferedReader(new InputStreamReader(System.in));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void run() {
    
            while (true) {
                try {
                    String data = reader.readLine();
                    byte[] datas = data.getBytes();
                    DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress(this.toIP, this.toPort));
    
                    socket.send(packet);
                    if (data.equals("bye")) {
                        break;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            socket.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 接收类
    public class TalkReveive implements Runnable{
        DatagramSocket socket = null;
        private int port;
        private String masFrom;
    
        public TalkReveive(int port, String masFrom) {
            this.port = port;
            this.masFrom = masFrom;
            try {
                socket = new DatagramSocket(port);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void run() {
    
            while (true) {
                try {
                    //准备接收包裹
                    byte[] container = new byte[1024];
                    DatagramPacket packet = new DatagramPacket(container, 0, container.length);
                    socket.receive(packet); //阻塞式接收包裹
    
                    //断开连接  bye
                    byte[] data = packet.getData();
                    String receiveData = new String(data, 0, data.length);
                    System.out.println(masFrom + ":" + receiveData);
    
                    if (receiveData.equals("bye")) {
                        break;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            socket.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 学生端
    public class TalkStudent {
        public static void main(String[] args) {
            //开启两个线程
            new Thread(new TalkSend(7777, "localhost", 9999)).start();
            new Thread(new TalkReveive(8888, "老师")).start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 老师端
    public class TalkTeacher {
        public static void main(String[] args) {
            //开启两个线程
            new Thread(new TalkSend(5555, "localhost", 8888)).start();
            new Thread(new TalkReveive(9999, "学生")).start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    八、URL

    https://www.baidu.com/
    统一资源定位符:定位资源的,定位互联网上的某一个资源
    DNS 域名解析:将www.baidu.com解析为IP

    协议://ip地址:端口/项目名/资源
    
    • 1

    URL类

    public class URLDemo01 {
        public static void main(String[] args) throws MalformedURLException {
            URL url = new URL("http://localhost:8080/helloworld/index.jsp?username=kuangshen&password=123");
            //协议
            System.out.println(url.getProtocol()); // http
            //主机ip
            System.out.println(url.getHost()); // localhost
            //端口
            System.out.println(url.getPort()); // 8080
            //文件
            System.out.println(url.getPath()); // /helloworld/index.jsp
            //文件全路径
            System.out.println(url.getFile()); // /helloworld/index.jsp?username=kuangshen&password=123
            //参数
            System.out.println(url.getQuery()); // username=kuangshen&password=123
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    使用URL下载网络资源

    public class UrlDown {
        public static void main(String[] args) throws Exception{
            //1. 下载地址
    //        URL url = new URL("http://localhost:8080/liang/SecurityFile.txt");
            URL url = new URL("https://m701.music.126.net/20220828003002/cd1e31a16d1baaf8802e609f390ee71b/jdyyaac/obj/w5rDlsOJwrLDjj7CmsOj/8419427026/04a2/5fe6/70b3/091231b04f70b2e0ea318711b3bd2609.m4a");
    
            //2. 连接到这个资源  HTTP
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
    
            InputStream is = urlConnection.getInputStream();
    
    //        FileOutputStream fos = new FileOutputStream("SecurityFile.txt");
            FileOutputStream fos = new FileOutputStream("music.m4a");
            byte[] buffer = new byte[1024];
            int len;
            while ((len = is.read(buffer)) != -1) {
                fos.write(buffer, 0, len); //写出这个数据
            }
            fos.close();
            is.close();
            urlConnection.disconnect();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
  • 相关阅读:
    sso单点登录的实现。
    【网络协议】聊聊网络路由相关算法
    (附源码)ssm在线学习网站 毕业设计 080833
    统计力学中的概率论基础(二)
    每日简报 8月30日简报新鲜事 每天一分钟 了解新鲜事
    60.WEB渗透测试-信息收集- 端口、目录扫描、源码泄露(8)
    3 UI开发的点点滴滴
    Golang 数组和切片
    OWASP-TOP10漏洞-注入漏洞
    服务器常用端口号及作用
  • 原文地址:https://blog.csdn.net/m0_61467488/article/details/126515021