JAVA学习打卡第十二天——网络编程

JAVA学习打卡第十二天

学习视频

什么是网络编程

  • 在网络通信协议下,不同计算机上运行的程序,进行的数据传输

  • 应用场景:即时通信、网游对战、金融证券、国际贸易、邮件等等

    不管是什么场景,都是计算机跟计算机之间通过网络进行数据传输

  • Java中可以使用java.net包下的技术轻松开发出常见的网络应用程序

  • 常见的软件架构:

    • CS:C/S —> Client/Server —> 客户端/服务器 —> 在用户本地需要下载并安装客户端程序,在远程有一个服务器端程序
    • BS:B/S —> Browser/Server —> 浏览器/服务器 —> 只需要一个浏览器,用户通过不同的网址。用户访问不同的服务器
    • 两种架构的对比:
      • BS架构优缺点:
        • 不需要开发客户端,只需要页面+服务端
        • 用户无需下载,打开浏览器就能使用
        • 如果应用过大,用户体验受到影响
      • CS架构优缺点:
        • 画面可以做的非常精美,用户体验好
        • 需要开发客户端,也需要开发服务端
        • 用户需要下载和更新的时候太麻烦

网络编程三要素

  • 网络编程三要素:

    • IP:设备在网络中的地址,是唯一的标识

    • 端口号:应用程序在设备中唯一的标识

    • 协议:数据在网络中传输的规则,常见的协议有UDP、TCP、http、https、ftp

IP

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

    通俗理解:上网设备在网络中的地址,是唯一的

  • 常见的IP分类为:IPv4、IPv6

  • IPv4

    • 全称:Internet Protocol version 4,互联网通信协议第四版
    • 采用32位地址长度,分成4组
    • IPv4采用点分十进制表示法
    • 一共只有不到43亿个地址,不够用。2019年11月26日全部分配完毕
    • IPv4的地址分类形式
      • 公网地址(万维网使用)和私有地址(局域网使用)
      • 192.168.开头的就是私有地址,范围即为192.168.0.0 – 192.168.255.255,专门为组织机构内部使用,以此节省IP
    • 特殊IP地址:127.0.0.1,也可以是localhost,是回送地址,也称本地回环地址,也称本机IP,永远只会寻找当前所在本机
    • 常用CMD命令:
      • ipconfig:查看本机IP地址
      • ping:检查网络是否连通
  • IPv6

    • 全称:Internet Protocol version 6,互联网通信协议第六版

    • 由于互联网的蓬勃发展,IP地址的需求量愈来愈大,而IPv4的模式下IP的总数是有限的

    • 采用128位地址长度,分成8组

    • IPv6采用冒分十六进制表示法

      如果计算出的16进制表示形式中间有多个连续的0,则用0位压缩表示法:FF01:0:0:0:0:0:0:1101 —> FF01::1101

  • InetAddress的使用【查看API】

    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    public class MyInetAddressDemo_01 {
        public static void main(String[] args) throws UnknownHostException {
        /*
            static Ineraddress getByName(String host)  确定主机名称的IP地址。主机名可以是机器名称,也可以是IP地址
            String getHostName   获取此IP地址的主机名
            String getHostAddress()   返回文本显示中的IP地址字符串
         */
            //获取InetAddress的对象
            InetAddress address = InetAddress.getByName("狝狁");//address可以看成是电脑的对象
            System.out.println(address);
    
            String name = address.getHostName();
            System.out.println("主机名:" + name);
    
            String ip = address.getHostAddress();
            System.out.println("ip:" + ip);
        }
    }
    

    在这里插入图片描述

端口号

  • 应用程序在设备中唯一的标识
  • 由两个字节表示的整数,取值范围:0~65535
    • 其中0~1023之间的端口号用于一些知名的网络服务或者应用
    • 我们自己使用1024以上的端口号就可以
  • 一个端口号只能被一个应用程序使用

协议

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

  • OSI参考模型:世界互联协议标准,全球通信规范,单模型过于理想化,未能在因特网上进行广泛推广

  • TCP/IP参考模型(或TCP/IP协议):事实上的国际标准

    在这里插入图片描述

  • UDP协议

    • 用户数据报协议(User Datagram Protocol)
    • UDP是面向无连接通信协议
    • 速度快,有大小限制,以此最多发送64k,数据不安全,易丢失数据
  • TCP协议

    • 传输控制协议TCP(Transmission Control Protocol)
    • TCP协议是面向连接的通信协议
    • 速度慢,没有大小限制,数据安全

UDP通信程序

发送数据

  • 创建发送端的DatagramSocket对象

  • 数据打包(DatagramPacket)

  • 发送数据

  • 释放资源

  • 示例

    import java.io.IOException;
    import java.net.*;
    
    public class SendMessageDemo {
        public static void main(String[] args) throws IOException {
            //创建DatagramSocket对象
            /*
            细节:
                绑定端口,以后我们就是通过这个端口往外发送
                空参:所有可用的端口中随机选择一个进行使用
                有参:指定端口号进行绑定
             */
            DatagramSocket ds = new DatagramSocket();
            //打包数据
            String str = "hello world";
            byte[] bytes = str.getBytes();
    
            InetAddress address = InetAddress.getByName("127.0.0.1");
    
            int port = 10086;
            DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);
    
            //发送数据
            ds.send(dp);
    
            //释放资源
            ds.close();
        }
    }
    

接收数据

  • 创建接收端的DatagramSocket对象

  • 接收打包好的数据

  • 解析数据包

  • 释放资源

  • 示例

    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    
    public class ReceiveMessageDemo {
        public static void main(String[] args) throws IOException {
            //
    
            //创建DatagramSocket对象
            /*
            细节:
                在接收的时候,一定要绑定端口
                绑定的端口必须跟发送的端口保持一致
             */
            DatagramSocket ds = new DatagramSocket(10086);
    
            //接收数据包
            byte[] bytes = new byte[1024];
            DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
            ds.receive(dp);//该方法是阻塞的,程序执行到这里时,会在这里死等,等待发送端发送消息
    
            //解析数据包
            byte[] data = dp.getData();
            int length = dp.getLength();
            InetAddress address = dp.getAddress();
            int port = dp.getPort();
            System.out.println("接收到数据" + new String(data, 0, length));
            System.out.println("数据是从" + address + "这个电脑中的" + port + "端口中发出的");
    
            //释放资源
            ds.close();
        }
    }
    

    注意,要先运行接收端,再运行发送端

  • 练习(聊天室)

    • 按照以下要求实现程序:
      • UPD发送数据:数据来自于键盘录入,直到输入886,发送数据结束
      • UDP接收数据:因为接收端不知道发送端什么时候停止发送,故采用死循环接收
  • 示例

    import java.io.IOException;
    import java.net.*;
    import java.util.Scanner;
    
    public class SendMessage {
        public static void main(String[] args) throws IOException {
            //创建对象
            DatagramSocket ds = new DatagramSocket();
            //打包数据
            Scanner sc = new Scanner(System.in);
            while (true) {
                System.out.println("请输入你要说的话:");
                String s = sc.nextLine();
    
                if (s.equals("886")) {
                    break;
                }
    
                byte[] bt = s.getBytes();
    
                InetAddress address = InetAddress.getByName("127.0.0.1");
    
                int port = 10086;
    
                DatagramPacket packet = new DatagramPacket(bt, bt.length, address, port);
    
                //发送数据
                ds.send(packet);
            }
            //释放资源
            ds.close();
        }
    }
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    
    public class RecieveMessage {
        public static void main(String[] args) throws IOException {
            //创建对象
            DatagramSocket ds = new DatagramSocket(10086);
            //接受数据包
            byte[] bytes = new byte[1024];
            DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
            while (true) {
                ds.receive(dp);
                //解析数据包
                byte[] data = dp.getData();
                int len = dp.getLength();
                String ip = dp.getAddress().getHostAddress();
                String name = dp.getAddress().getHostName();
                //打印数据
                System.out.println("ip为" + ip + ",主机名为" + name + "的人发送了数据:" + new String(data, 0, len));
            }
        }
    }
    

UDP三种通信方式

  • 单播

  • 组播:组播地址—>224.0.0.0 ~ 239.255.255.255—>其中224.0.0.0 ~ 224.0.0.255为预留的组播地址

  • 广播:广播地址—>255.255.255.255

  • 示例(组播)

    import java.io.IOException;
    import java.net.*;
    
    public class SendMessageDemo {
        public static void main(String[] args) throws IOException {
            //创建对象
            MulticastSocket ms = new MulticastSocket();
            //打包数据
            String str = "hello world";
            byte[] bytes = str.getBytes();
    
            InetAddress address = InetAddress.getByName("224.0.0.1");
    
            int port = 10086;
            DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);
    
            //发送数据
            ms.send(dp);
    
            //释放资源
            ms.close();
        }
    }
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.InetAddress;
    import java.net.MulticastSocket;
    
    public class ReceiveMessageDemo_01 {
        public static void main(String[] args) throws IOException {
            //创建对象
            MulticastSocket ms = new MulticastSocket(10086);
    
            //将当前本机,添加到224.0.0.1的这一组当中
            InetAddress address = InetAddress.getByName("224.0.0.1");
            ms.joinGroup(address);
    
            //接收数据包
            byte[] bytes = new byte[1024];
            DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
            ms.receive(dp);
    
            //解析数据包
            byte[] data = dp.getData();
            int len = dp.getLength();
            String ip = dp.getAddress().getHostAddress();
            String name= dp.getAddress().getHostName();
            System.out.println("ip为" + ip + ",主机名为" + name + "的人发送了数据:" + new String(data, 0, len));
    
            //释放资源
            ms.close();
        }
    }
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.InetAddress;
    import java.net.MulticastSocket;
    
    public class ReceiveMessageDemo_02 {
        public static void main(String[] args) throws IOException {
            //创建对象
            MulticastSocket ms = new MulticastSocket(10086);
    
            //将当前本机,添加到224.0.0.1的这一组当中
            InetAddress address = InetAddress.getByName("224.0.0.1");
            ms.joinGroup(address);
    
            //接收数据包
            byte[] bytes = new byte[1024];
            DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
            ms.receive(dp);
    
            //解析数据包
            byte[] data = dp.getData();
            int len = dp.getLength();
            String ip = dp.getAddress().getHostAddress();
            String name= dp.getAddress().getHostName();
            System.out.println("ip为" + ip + ",主机名为" + name + "的人发送了数据:" + new String(data, 0, len));
    
            //释放资源
            ms.close();
        }
    }
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.InetAddress;
    import java.net.MulticastSocket;
    
    public class ReceiveMessageDemo_03 {
        public static void main(String[] args) throws IOException {
            //创建对象
            MulticastSocket ms = new MulticastSocket(10086);
    
            //将当前本机,添加到224.0.0.1的这一组当中
            InetAddress address = InetAddress.getByName("224.0.0.2");
            ms.joinGroup(address);
    
            //接收数据包
            byte[] bytes = new byte[1024];
            DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
            ms.receive(dp);
    
            //解析数据包
            byte[] data = dp.getData();
            int len = dp.getLength();
            String ip = dp.getAddress().getHostAddress();
            String name= dp.getAddress().getHostName();
            System.out.println("ip为" + ip + ",主机名为" + name + "的人发送了数据:" + new String(data, 0, len));
    
            //释放资源
            ms.close();
        }
    }
    
  • 示例(广播)

    只需要将单播中的发送地址改为“255.255.255.255”即可

TCP通信程序

  • TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象

  • 通信之前要保证连接已建立

  • 通过Socket产生IO流来进行网络通信

  • 客户端:

    • 创建客户端的Socket对象(Socket)与指定服务端连接

      Socket(String host, int port)

    • 获取输出流,写数据

      OutputStream getOutputStream()

    • 释放资源

      viod close

  • 服务器

    • 创建服务器端的Socket对象(ServerSocket)

      ServerSocket(int port)

    • 监听客户端连接,返回一个Socket对象

      Socket accept()

    • 获取输入流,读数据,并将数据显示在控制台

      InputStream getInputStream()

    • 释放资源

      void close()

  • 注意:要先启动服务端,再启动客户端

  • 示例

    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.Socket;
    
    public class Client {
        public static void main(String[] args) throws IOException {
            //创建对象
            /*
            细节:
                在创建对象的同时会连接服务端,
                如果连接不上,代码会报错
             */
            Socket socket = new Socket("127.0.0.1", 10086);
    
            //可以从连接通道中,获取输出流
            OutputStream os = socket.getOutputStream();
            //写数据
            os.write("aaa".getBytes());
            //释放资源
            os.close();
            socket.close();
        }
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class Server {
        public static void main(String[] args) throws IOException {
            //创建对象
            ServerSocket ss = new ServerSocket(10086);
            //监听客户端连接
            Socket socket = ss.accept();
            //从连接通道中获取输入流
            InputStream is = socket.getInputStream();
            int b;
            while ((b = is.read()) != -1) {
                System.out.print((char) b);
            }
    
            //释放资源
            socket.close();
            ss.close();
            is.close();//IO流在Socket通道内部,关闭通道时,IO流会自动关闭
        }
    }
    
  • 三次握手

    • 作用:确保连接建立
    • 过程:
      • 客户端向服务器发出连接请求,等待服务器确认
      • 服务器向客户端返回一个响应,告诉客户端收到了请求
      • 客户端向服务器再次发出确认信息,连接建立
  • 四次挥手

    • 作用:确保连接断开,且数据处理完毕
    • 过程:
      • 客户端向服务器发出取消连接请求
      • 服务器向客户端返回一个响应,表示收到客户端取消请求
      • 服务器将最后的数据处理完毕,向客户端发出确认取消信息
      • 客户端再次发送确认消息,连接取消

综合练习

  • 24
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值