Java基础学习(十七)

Java基础学习(十七):网络编程

本文为个人学习记录,内容学习自 黑马程序员


概念

  • 定义:在网络通信协议下,不同计算机上运行的程序进行的数据传输
  • 常见的软件架构:C/S 和 B/S
    • C/S:Client/Server,在用户本地需要下载并安装客户端程序,在远程有一个服务器端程序
    • B/S:Browser/Server,用户通过浏览器的不同网址即可访问不同的服务器
  • C/S 和 B/S 的比较:
    • C/S 需要开发客户端,适合定制专业化的办公类软件,例如 IDEA、网游
    • B/S 不需要开发客户端,适合移动互联网应用,例如新闻网页
  • 网络编程三要素:IP、端口号、协议
    • IP:设备在网络中的地址,是唯一的标识
    • 端口号:应用程序在设备中唯一的标识
    • 协议:数据在网络中传输的规则,常见的协议有 UDP、TCP、http、https、ftp

IP

  • 定义:全称 Internet Protocol,互联网协议地址,也称 IP 地址,是分配给上网设备的数字标签

  • 常见分类:IPv4、IPv6

  • IPv4:Internet Protocol version 4,互联网通信协议第四版

    • 采用 32 位地址长度,分成 4 组
    • 通常采用点分十进制表示,例如 11000000 10101000 00000001 01000010 表示为 192.168.1.66(没有负数)
  • IPv6:Internet Protocol version 6,互联网通信协议第六版

    • 采用 128 位地址长度,分成 8 组
    • 通常采用冒分十六进制表示
  • 现状:IPv4 不够用,但 IPv6 还未普及,IPv4 仍是使用的主流,为了节省 IP 地址,又将 IPv4 的地址分成了公网地址(万维网使用)和私有地址(局域网使用),192.168. 开头的就是私有地址,专门为组织机构内部使用,例如网吧中的电脑共享一个对外的公网 IP,再由路由器给其中的每一台电脑分配局域网 IP

  • 特殊 IP 地址:127.0.0.1,也称为 localhost,是本地回环地址,也即本机 IP

  • 举例:假如本机 IP 的局域网地址为 192.168.1.100,那么通过 192.168.1.100 和 127.0.0.1 都可以访问到本机,但前者需要经由路由器才能将信息发送到本机,而后者可以直接发送到本机,并且前者在不同路由器下分配的地址可能不同,而后者固定不变

  • 常见 CMD 命令:

    • ipconfig:查看本机 IP 地址
    • ping:检查网络是否连通
  • InetAddress

    常用方法 说明
    static InetAddress getByName(String host) 确定主机名称的 IP 地址,主机名称可以是机器名称,也可以是 IP 地址
    String getHostName() 获取此 IP 地址的主机名
    String getHostAddress() 返回文本显示中的 IP 地址字符串
    public class Test {
        public static void main(String[] args) throws UnknownHostException {
            InetAddress address = InetAddress.getByName("10.250.206.75");
            String name = address.getHostName();
            String ip = address.getHostAddress();
        }
    }
    

端口号

  • 端口号是应用程序在设备中的唯一标识
  • 端口号由两个字节表示,取值范围:0 ~ 65535,其中 0 ~ 1023 端口号用于一些知名的网络服务或者应用

协议

计算机网络中,连接和通信的规则被称为网络通信协议

  • OSI 参考模型:世界互联协议标准,全球通信规范,由于过于理想化而未能推广
  • TCP/IP 参考模型(TCP/IP协议):事实上的国际标准

图17-1

UDP 通信

  • User Datagram Protocol,用户数据报协议

  • 面向无连接的通信协议,速度快,有大小限制一次最多发送 64K,数据不安全,易丢失数据

  • UDP 通信程序(发送数据)

    • 步骤:① 创建发送端的 DatagramSocket 对象 ② 数据打包(DatagramPacket) ③ 发送数据 ④ 释放资源

    • 代码实现:

      public class Test {
          public static void main(String[] args) throws IOException {
              // 1.创建DatagramSocket对象
              // 需要绑定端口,之后就从这个端口向外发送
              // 采用空参构造时,从所有可用端口中随机选择绑定
              // 采用有参构造时,指定端口号进行绑定
              DatagramSocket ds = new DatagramSocket();
      
              // 2.打包数据
              // 创建DatagramPacket对象进行数据打包,DatagramPacket有多种构造方法,下面列举其中一种
              // 第一个参数为要发送的字节数组
              // 第二个参数为要发送数据的长度
              // 第三个参数为目标IP地址,为InetAddress对象
              // 第四个参数为目标端口
              String str = "你好";
              byte[] bytes = str.getBytes();
              InetAddress address = InetAddress.getByName("127.0.0.1");
              int port = 10086;
              DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);
      
              // 3.发送数据
              ds.send(dp);
      
              // 4.释放资源
              ds.close();
          }
      }
      
  • UDP 通信程序(接收数据)

    • 步骤:① 创建接收端的 DatagramSocket 对象 ② 接收打包好的数据 ③ 解析数据包 ④ 释放资源

    • 代码实现:

      public class Receive {
          public static void main(String[] args) throws IOException {
              // 1.创建DatagramSocket对象
              // 接收时必须绑定端口,并且端口号必须和发送端的目标端口一致
              DatagramSocket ds = new DatagramSocket(10086);
      
              // 2.接收数据包
              // 创建DatagramPacket对象进行数据打包,DatagramPacket有多种构造方法,在接收数据时只需要指定接收数组和长度
              // receive()方法是阻塞的
              byte[] bytes = new byte[1024];
              DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
              ds.receive(dp);
      
              // 3.解析数据包
              // 可以获取数据包中的数据值、数据长度、发送端IP地址对象、发送端端口号
              byte[] data = dp.getData();
              int len = dp.getLength();
              InetAddress address = dp.getAddress();
              int port = dp.getPort();
              System.out.println(new String(data, 0, len));
      
              // 4.释放资源
              ds.close();
          }
      }
      
  • UDP 的三种通信方式:单播、组播、广播

    • 单播:一个发送端,一台电脑作为接收端

      • 上面的代码即是单播的实现
    • 组播:一个发送端,一组电脑作为接收端

      • 组播地址:224.0.0.0 ~ 239.255.255.255,其中 224.0.0.0 ~ 224.0.0.255 为预留给个人的组播地址

      • 代码实现(发送端)

        public class Send {
            public static void main(String[] args) throws IOException {
                // 1.创建MulticastSocket对象
                MulticastSocket ms = new MulticastSocket();
        
                // 2.打包数据
                // 目标IP地址为组播地址中
                String str = "你好";
                byte[] bytes = str.getBytes();
                InetAddress address = InetAddress.getByName("224.0.0.1");
                int port = 10000;
                DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);
        
                // 3.发送数据
                ms.send(dp);
        
                // 4.释放资源
                ms.close();
            }
        }
        
      • 代码实现(接收端)

        public class Receive {
            public static void main(String[] args) throws IOException {
                // 1.创建MulticastSocket对象
                MulticastSocket ms = new MulticastSocket(10000);
        
                // 2.将本机添加到要使用的组播地址中
                InetAddress address = InetAddress.getByName("224.0.0.1");
                ms.joinGroup(address);
        
                // 3.接收数据包
                byte[] bytes = new byte[1024];
                DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
                ms.receive(dp);
        
                // 4.解析数据包
                byte[] data = dp.getData();
                int len = dp.getLength();
                InetAddress ip = dp.getAddress();
                int port = dp.getPort();
        
                // 5.释放资源
                ms.close();
            }
        }
        
    • 广播:一个发送端,局域网中所有电脑都是接收端

      • 广播地址:255.255.255.255

      • 代码实现(发送端)

        public class Send {
            public static void main(String[] args) throws IOException {
                // 1.创建DatagramSocket对象
                DatagramSocket ds = new DatagramSocket();
        
                // 2.打包数据
                // 目标IP地址为广播地址
                String str = "你好";
                byte[] bytes = str.getBytes();
                InetAddress address = InetAddress.getByName("255.255.255.255");
                int port = 10000;
                DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);
        
                // 3.发送数据
                ds.send(dp);
        		
                // 4.释放资源
                ds.close();
            }
        }
        

TCP 通信

  • Transmission Control Protocol,传输控制协议

  • 面向连接的通信协议,速度慢,没有大小限制,数据安全

  • TCP 通信协议是一种可靠的网络协议,它在通信的两端各建立一个 Socket 对象,通信之前要保证连接已经建立,通过 Socket 产生 IO 流来进行网络通信

  • TCP 通信程序(客户端)

    • 步骤:① 创建客户端的 Socket 对象(Socket)与指定服务端连接 ② 获取输出流 ③ 写数据 ④ 释放资源

    • 代码实现:

      public class Client {
          public static void main(String[] args) throws IOException {
              // 1.创建Socket对象
              // 参数一:要连接的IP地址
              // 参数二:要连接的端口号
              // 注意:如果连接不上,代码会报错(必须先启动服务器端,再启动客户端)
              Socket socket = new Socket("127.0.0.1", 10000);
      
              // 2.从连接通道中获取输出流
              // 需要注意:客户端也能使用socket.getInputStream()获取输入流,从服务端接收数据
              OutputStream os = socket.getOutputStream();
      
              // 3.向输出流中写入数据
              os.write("你好".getBytes());
      
              // 4.释放资源
              // 释放socket时也会释放内部的输出流
              socket.close();
          }
      }
      
  • TCP 通信程序(服务器端)

    • 步骤:① 创建服务器端的 Socket 对象(ServerSocket) ② 监听客户端连接,返回一个 Socket 对象 ③ 获取输入流,读数据 ④释放资源

    • 代码实现:

      public class Server {
          public static void main(String[] args) throws IOException {
              // 1.创建ServerSocket对象
              // 参数为绑定的端口号,需要和客户端要连接的端口号一致
              ServerSocket ss = new ServerSocket(10000);
      
              // 2.监听客户端的连接
              // 这一步会阻塞程序
              Socket socket = ss.accept();
      
              // 3.从连接通道中获取输入流,读取数据
              // 需要注意:服务端也能使用socket.getOutputStream()获取输出流,向客户端写入数据
              InputStream is = socket.getInputStream();
              // (可选)为了正确读取中文,需要使用转换流
              InputStreamReader isr = new InputStreamReader(is, "UTF-8");
              int b;
              // read()方法会从连接通道中读取数据,只有读取到结束标记时返回值才为-1
              // 结束标记一般有两种写法:
              // 1.在客户端使用socket.shutdownOutput()关闭输出流
              // 2.在客户端使用socket.close()关闭socket
              while ((b = isr.read()) != -1) {
                  System.out.print((char) b);
              }
      
              // 4.释放资源
              // 释放socket时也会释放内部的输入流
              socket.close();
              ss.close();
          }
      }
      
  • TCP 通信中的“三次握手”和“四次挥手”:

    • 三次握手

      图17-2
    • 四次挥手

      图17-3

posted @   victoria6013  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示