网络编程;InetAddress类;UDP协议和TCP协议;Socket编程;UDP编程;TCP编程 (Java Day26)

一,网络编程概念

  • 网络:就是不同地域,不同型号、不同ip等多台计算机相互连接沟通形成的通信系统
  • ​ 元素:
  1. ​ 看得见的元素:网线、交换机、计算机、内存条等一系列的硬件设备
  2. ​ 看不见的元素:传输协议、io流、运行的程序等
  • 网络编程:基于计算机网络来进行数据的接收,发送,处理等操作的过程会使用不同的语言来实现。比如 java c++ 等
  • 网络编程三要素:ip地址、端口号、传输协议

  • IP地址

  • 概述:计算机在网络中IP协议分配给每一台计算机的唯一标识。【他代表了计算机在网络中唯一地址。通过ip可以找到想要找的计算机】
  • 作用:能够在网络准确找到计算机
  • 分类:IPv4:是由四个字节组成的一段序列,来表示计算机的标识,字节和字节之间使用.隔开。一个字节8位,4个字节是32位,一共有2^32个ip。大概42亿个ip,也就是说他可以给42亿台计算机分配地址。
  • ​ 比如:192.168.1.148
  • ​ 一般前三个字节代表的是子网段的,最后一个字节代表计算机的段号。每一个字节都是0到255之间的数
  • IPv6:8组16进制的数组成的一段序列,来表示ip地址。组与组之间使用 :隔开。每组数有16种变化,一共128位,2^128个ip,号称全世界每一粒沙子都有一个ip。
  • ​ 比如:fe80::741f:ab6d:2237:20af%13,
  • 如果是0可以省略,一般是连续为0.
  • 端口号【重点】

  • 概述:就是一个数字,是计算机中正在运行的进程的编号。端口号不可以重复。他是由2个字节大小的数字来表示,0到65535的范围。
  • 作用:能够通过他准确的找到计算机中正在运行的进程
  • 端口号的分配:
  1. 程序在启动的时候计算机随机自动分配端口号
  2. 程序中人为的指定端口号 比如 : 第二阶段 安装 mysql 时会有一个端口号设置 3306 【默认的】一般情况下默认不改
  • 常用的端口号:
  1. ​ 系统程序:0到1024
  2. ​ MySQL:3306
  3. ​ Oracle:1521
  4. ​ Tomcat:8080
  5. ​ QQ:4000
  • 通信协议

  • 概述:数据在传输过程中接收、发送,处理等操作是有规则。不同的场景有不同的协议,往往不同的协议协同合作维护网络编程的环境。
  • 网络分层:分工作业
  1. ​ 应用层:对数据的发送和接收进行处理工作 HTTP协议、HTTPS协议、FTP协议。
  2. ​ 传输层:把数据从一端传输到另一端 TCP协议 UDP协议【今天要讲的协议】
  3. ​ 网络层:规划线路连接 IP协议
  4. ​ 物理层:相关的硬件设施

二,InetAddress类

  • 概述:此类表示互联网协议 (IP) 地址。【对ip的相关特征和行为的描述,一般包括主机和IP地址】
  • 获取对象的方式:【静态方法
  1. ​ getAllByName(String host) :  通过主机名称获取对应的所有IP地址对象的数组
  2. ​ getByAddress(byte[] addr) :通过IP地址的字节数组获取IP地址的对象
  3. ​ getByAddress(String host, byte[] addr) :通过主机名称和IP地址的字节数组获取IP地址的对象
  4. getByName(String host) :通过主机名称获取对应的IP地址对象
  5. ​ getLocalHost() :获取本地主机的IP对象

代码示例:


import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
public class Demo_InetAddress {
    public static void main(String[] args) throws UnknownHostException {
        InetAddress[] allByName = InetAddress.getAllByName("APPLE-NO-MBP"); // 主机名
        System.out.println(Arrays.toString(allByName)); // [APPLE-NO-MBP/192.168.43.61],获取主机名称和IP地址

        // 127.0.1 本机的IP地址 对应的字节数组 127 0 0 1
        byte[] bs = { 127, 0, 0, 1 };
        InetAddress address = InetAddress.getByAddress(bs);
        System.out.println(address); // 127.0.0.1,将数组变为IP地址,数组与IP地址之间的转化

        InetAddress address2 = InetAddress.getByAddress("APPLE-NO-MBP", bs);
        System.out.println(address2); // APPLE-NO-MBP/127.0.0.1,显示哪台机器下面的IP,包括主机名称和IP地址

        InetAddress address3 = InetAddress.getByName("APPLE-NO-MBP");
        System.out.println(address3); // APPLE-NO-MBP/192.168.43.61 获取的是主机和IPV4地址

        InetAddress host = InetAddress.getLocalHost();
        System.out.println(host); // apple-no-MBP/192.168.43.61, 获取自己电脑的IP地址

 

  • 获取对象的属性常用方法:
  1. ​ getAddress() :返回对象的原始IP地址
  2. ​ getHostName(): 返回对象的主机名称
  3. ​ toString() :将ip地址转换为字符串

代码示例


import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
public class Demo_InetAddress {
    public static void main(String[] args) throws UnknownHostException {
        InetAddress host = InetAddress.getLocalHost();
        System.out.println(host); // apple-no-MBP/192.168.43.61, 获取自己电脑的IP地址

        // 常用方法
        byte[] bs2 = host.getAddress(); // IP 的字节数组
        System.out.println(Arrays.toString(bs2)); // [-64, -88, 43, 61], 因为192超出了字节的范围,溢出了
        InetAddress address5 = InetAddress.getByAddress(bs2);
        System.out.println(address5); // /192.168.43.61 转回为数组
        
        String name = host.getHostName();
        System.out.println(name);  //apple-no-MBP 返回对象的主机名称
        System.out.println(host.toString());  //apple-no-MBP/192.168.43.61, 将ip地址转换为字符串
    }
}

 

三,UDP协议和TCP协议

  • 概述:是传输层的协议,是数据端到端的协议
  • UDP:  是面向无连接的协议。不用端和端之间联系就进行数据的传输。比如:QQ发消息、短信、微博留言、邮件等方式。所以不用管对方在不在线,直接操作数据,但是数据发出去之后有可能收不到,安全性低,效率高。不区分客户端和服务端,只有发送端和接收端。
  • 特点:
  1. 数据不安全
  2. 效率高
  • TCP:面向连接的传输协议。要求对方必须在线并且连接成功。区分客户和服务,把发送数据段叫做客户端,接收数据端就做服务端。
  • ​ 如何进行连接的?
  • ​ 三次握手:瞬间就可以完成的。
  1. ​ 第一次:发送端发出信号给接收端
  2. ​ 第二次:接收端接到信号给出回应
  3. ​ 第三次:发送端收到回应确定连接成功
  • 特点:
  1. 数据安全性有保证
  2. 效率低

四,Socket编程【套接字编程】

  • Socket :  套接字
  • ​ 套接字:传输层编程是端到端的编程,套接字就是端和端进行交流的中间服务
  • ​ 举例: 网购 客户 网上买了东西 商家 把东西邮寄给你
  • ​ 客户:发送端
  • ​ 商家: 服务端
  • ​ 快递:把货在商家和客户之间进行传输 就是套接字
  • Socket编程在不同的协议下使用的套接字不一样。
  • UDP协议:DatagramSocket
  • TCP协议:
  1. ​ 客户端:Socket
  2. ​ 服务端:ServerSocket

五,UDP编程

  • DatagramSocket:他是UDP编程的套接字 ,此类表示用来发送和接收数据报包的套接字
  • 数据报包【DatagramPacket】:指包装了发送的数据和接收数据数据的一个容器。【发送和接收的内容、发送的ip地址、端口号等内容】
  • 构造方法
  1. DatagramSocket():获取套接字对象【一般用于发送端】
  2. DatagramSocket(int port):获取套接字对象【一般用于接收端】
  • 常用方法:
  1. ​ send(DatagramPacket dp):发送数据报包出去
  2. ​ receive(DatagramPacket dp):接收数据报包
  3. DatagramPacket :数据报包
  • 通过构造方法来封装相关数据的构造方法:
  1. ​ DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port) :用于发送端
  2. ​ DatagramPacket(byte[] buf, int offset, int length) :用于接收端
  • ​ 说明:
  1. buf:存放发送或接收数据内容的字节数组
  2. offset:buf 数组从哪个角标开始发送或接收,代表开始的角标值
  3. length:代表发送内容的长度,或者接受数组长度
  4. address:发送端发送目标ip地址
  5. port:发送的目标端口号
  • 数据报包的常用方法【获取数据报包内部的数据的方法】
  1. getData():获取数据报包中的内容数组
  2. ​ getLength():获取数据报包中有效内容的长度

代码示例1,UDP发送端

  • 发送端编写步骤:
  1. 获取套接字对象
  2. 准备发送的相关数据
  3. 获取数据报包同时封装发送的数据
  4. 发送数据报包
  5. 准备接收数据的容器【字节数组相关数据】
  6. 准备一个接收数据的数据报包
  7. 接收数据
  8. 解析数据

import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException;
// 发送端 public class UDP_Send { public static void main(String[] args) throws Exception { // 创建发送端的套接字对象 DatagramSocket socket = new DatagramSocket(); byte[] buf = "美女你好".getBytes(); DatagramPacket packet = new DatagramPacket(buf, 0, buf.length, InetAddress.getLocalHost(), 9999); socket.send(packet); // 接收发送端的回复 byte[] buf1 = new byte[1024]; DatagramPacket packet1 = new DatagramPacket(buf, 0, buf.length); socket.receive(packet1); // 如何获取接收到的数据呢? byte[] bs = packet1.getData();// 获取到数据报包中的读取内容的数组 int len = packet1.getLength();// 获取到有效内容的字节个数 System.out.println(new String(bs , 0 , len)); } }

代码示例2:UDP接收端

  • 接收端编写步骤:
  1. 获取套接字
  2. 准备接收容器【字节数组的相关数据】
  3. 接收数据到数据报包
  4. 解析接收到的数据【数据报包方法】
  5. 准备回应的内容【字节数组】
  6. 将内容添加到接收使用的数据报包中
  7. 将该数据报包发送回发送端

import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException;
// 接收端 public class UDP_Receive { public static void main(String[] args) throws Exception { // 创建套接字对象 DatagramSocket socket = new DatagramSocket(9999); byte[] buf = new byte[1024]; DatagramPacket packet = new DatagramPacket(buf, 0, buf.length); socket.receive(packet); // 如何获取接收到的数据呢? byte[] bs = packet.getData();// 获取到数据报包中的读取内容的数组 int len = packet.getLength();// 获取到有效内容的字节个数 System.out.println(new String(bs , 0 , len)); // 接收端要给个回应 byte[] bs2 = "帅哥你好".getBytes(); packet.setData(bs2); socket.send(packet);
} }

 六,TCP编程

  • 客户端
  1. Socket:此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点
  • ​ 构造方法
  1. ​ Socket(InetAddress address, int port) :创建套接字对象,包含了目标的ip和端口号
  2. ​ 发送和接收数据采用的是io流技术,套接字发送和接收数据,先获取对用的流对象。
  • ​ 常用功能
  1. ​ getOutputStream() :获取字节输出流【专门使用在客户端和服务端流的目标就是客户端和服务端】
  2. ​ getInputStream() :获取字节输入流
  • 服务端
  • ServerSocket:此类实现服务器套接字。服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果
  • 某些操作:ServerSocket套接字侦听客户端套接字是否入侵服务端,侦听到客户端的套接字,要和该套接字交流,找一个和客户端同一类型的套接字对象。
  • ​ 构造方法:
  1. ​ ServerSocket(int port):创建服务端的套接字对象【内含端口号】
  • ​ 常用方法
  1.  accept() :获取一个和客户端类型一致的套接字对象

代码示例1:TCP客户端

  • 步骤:
  1. 创建Socket套接字对象
  2. 获取字节输出流
  3. 使用输出流写出内容
  4. 获取字节输入流
  5. 创建读取内容的字节数组
  6. 读取内容
  7. 解析内容
  8. 关闭流资源

import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.util.Scanner;
public class TCP_Send { public static void main(String[] args) throws Exception, IOException { // 创建键盘录入对象 Scanner scanner = new Scanner(System.in); while(true) { // 创建客户端的套接字对象【链接服务器 需要传入服务器的ip和端口号】 Socket socket = new Socket(InetAddress.getLocalHost(), 9999); // 发送数据和接收数据需要相应的流对象 InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); System.out.println("请输入您要说的话:"); String next = scanner.next(); byte[] bs = next.getBytes(); // 把数据发送出去 os.write(bs); // 接收服务端的回复信息 byte[] bs1 = new byte[1024]; int i = is.read(bs1); System.out.println(new String(bs1,0,i)); os.close(); //关流 is.close(); //关流 } } }

代码示例2:TCP服务端

  • 步骤:
  1. 创建ServerSocket套接字对象
  2. 提供Socket套接字对象【好和客户端的套接字交流】
  3. 获取字节输入流
  4. 创建读取内容的字节数组
  5. 读取内容
  6. 解析内容
  7. 获取字节输出流
  8. 使用输出流写出内容
  9. 关闭流资源

import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner;
public class TCP_Receice { public static void main(String[] args) throws Exception { // 创建服务端的套接字对象 ServerSocket serverSocket = new ServerSocket(9999); // 创建键盘录入对象 Scanner scanner = new Scanner(System.in); while(true) { // 根据客户端的套接字对象生成对应的对象来进行正常的交流 Socket socket = serverSocket.accept(); // 得到输入流对象可以读取【接收发送过来的数据】 InputStream is = socket.getInputStream(); byte[] bs = new byte[1024]; int i = is.read(bs); System.out.println(new String(bs,0,i)); // 给客户端一个回复 OutputStream os = socket.getOutputStream(); System.out.println("请输入您要回复的话:"); String next = scanner.next(); byte[] bs2 = next.getBytes(); os.write(bs2); os.close(); //关流 is.close(); //关流 } } }
  • 加强:一个服务端 ,多个客户端的时候,单线程的时候,客户的需求服务端一个一个的处理,处理第一个客户需求的时候,其他的客户就得等着,处理完了才会处理下一个。同时接受多个客户的需求并进行处理

服务端代码:


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class TCP_Receice {
    public static void main(String[] args) throws Exception {
        // 创建服务端的套接字对象
        ServerSocket serverSocket = new ServerSocket(9999);
        // 创建键盘录入对象
        Scanner scanner = new Scanner(System.in);
        while(true) {
            // 根据客户端的套接字对象生成对应的对象来进行正常的交流
            // 服务端监测到一个客户端对象来 就给你分配一条线程【安排一个窗口不用等】
            Socket socket = serverSocket.accept();
            // 分配新的线程
            new Thread() {// 一个新的窗口
                public void run() {
                    // 得到输入流对象可以读取【接收发送过来的数据】
                    InputStream is = null;
                    OutputStream os = null;
                    try {
                        is = socket.getInputStream();
                        byte[] bs = new byte[1024];
                        int i = is.read(bs);
                        System.out.println(new String(bs,0,i));
                        
                        // 给客户端一个回复
                         os = socket.getOutputStream();
                        System.out.println("请输入您要回复的话:");
                        String next = scanner.next();
                        byte[] bs2 = next.getBytes();
                        os.write(bs2);  
                    } catch (IOException e) {
                        e.printStackTrace();
                    }finally {
                        try {
                            if (os != null) {
                                os.close();
                            }
                            if (is != null) {
                                is.close();
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        } 
                    }
                }
            }.start();
        }
    }
}

 

客户端代码:


import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.util.Scanner;
public class TCP_Send { public static void main(String[] args) throws Exception, IOException { // 创建键盘录入对象 Scanner scanner = new Scanner(System.in); while(true) { // 创建客户端的套接字对象【链接服务器 需要传入服务器的ip和端口号】 Socket socket = new Socket(InetAddress.getLocalHost(), 9999); // 发送数据和接收数据需要相应的流对象 InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); System.out.println("请输入您要说的话:"); String next = scanner.next(); byte[] bs = next.getBytes(); // 把数据发送出去 os.write(bs); // 接收服务端的回复信息 byte[] bs1 = new byte[1024]; int i = is.read(bs1); System.out.println(new String(bs1,0,i)); os.close(); //关流 is.close(); //关流 } }
posted @ 2020-03-31 12:20  娜梓  阅读(250)  评论(0编辑  收藏  举报