• Java网络编程


    一、网络编程三要素

    1、IP地址

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

    2、端口

    • 应用程序在设备中的唯一标识

    3、协议

    • 数据在网络中传输的规则,常见的协议有UDP协议和TCP协议

    二、IP地址

    1、含义

    • IP地址,全称为Internet Protocol Address,网络协议地址。是分配给上网设备的数字标签。
    • 常见的IP分类有ipv4和ipv6

    2、实践--终端ping网址

    • 在终端输入 ping www.itheima.com的过程解析

    3、分类

    ipv4:32bit来表示

    • 问题:ipv4能分配的地址数量最多为256的四次方个,约为42亿,数量逐渐不够使用

    ipv6:128bit来表示

    4、相关命令(Mac)

    • 查看本机的IP地址

      • ifconfig
      • ifconfig | grep net 用管道符号+grep命令来过滤一下,更方便查看
    • 检查网络是否连通(还可以确定域名的IP地址)

      • ping IP地址

    5、特殊IP

    • 127.0.0.1:回送地址,本地回环地址。可以代表本机的IP地址,一般用来测试使用

    6、Java中的InetAddress类

    6.1、含义

    • 表示IP地址

    6.2、常用方法

    • static InetAddress getByName("String host"):通过主机名获取InetAdress对象,host可以是主机名,也可以是IP地址
    • String getHostName():获取主机名
    • String getHostAddress():获取IP地址

    6.3、关于Mac查看和修改主机名和计算机名

    https://www.jianshu.com/p/dbf2fa105f26

    三、端口

    1、含义

    • 应用程序在设备中的唯一表示

    2、端口号

    • 用两个字节表示的整数来标识。范围0~25535
    • 0~1023之间的端口号常用于一些知名的网络服务或应用,我们自己使用1024及以上

    3、注意

    • 一个端口号只能被一个应用程序来使用

    四、协议

    1、UDP协议

    • UDP(User Datagram Protocol)用户数据报协议

    • 面向无连接:只管发送,不必先建立连接,都可以发送成功。如果两者已经连接,就能成功接收;

    • 特点

      • 速度快
      • 大小限制:最大为64K
      • 数据不安全,易丢失
    • 常见场景:音视频、普通数据

    2、TCP协议

    • TCP(Transmission Control Protocol)传输控制协议
    • 面向连接:先保证连接已经建立,才传输数据
    • 特点
      • 速度慢
      • 没有大小限制
      • 数据安全
    • 常用场景:聊天

    五、UDP通信程序

    1、发送端

    • 过程图示

    • 代码实现
    public class ClientDemo {
        public static void main(String[] args) throws IOException {
            //1.找码头
            DatagramSocket ds = new DatagramSocket();
    
            //2.打包数据
            String message = "你好哇,李婷婷!";
            byte[] bytes = message.getBytes();
            InetAddress address = InetAddress.getByName("127.0.0.1");
            int port = 10000;
            DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);
    
            //3.发送数据
            ds.send(dp);
    
            //4.释放资源
            ds.close();
        }
    }
    

    2、接收端

    • 过程图示

    • 代码实现
    public class ServerDemo {
        public static void main(String[] args) throws IOException {
            //1.找码头    ---表示从10000端口号接收数据,否则就是从随机端口接收数据
            DatagramSocket ds = new DatagramSocket(10000);
    
            //2.创建包
            byte[] bytes = new byte[1024];
            DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
    
            //3.接受包
            ds.receive(dp);
    
            //4.打开包得到数据
            byte[] data = dp.getData();
            System.out.println(new String(data));
    
            //5.释放资源
            ds.close();
        }
    }
    

    3、实现通信

    • 先运行接收端,保证建立了连接。
    • 再运行发送端,发送数据
    • 检查服务端,确实收到了数据

    4、注意

    1. 如果接收端没有收到数据,就会死等(阻塞)。可以在接收前后加上输出语句来验证
    2. 新数组接收到的数据中,如果不能填满,会包含空格,可以使用getLength()来获取数据的长度

    其实,数组data是多余的,直接用bytes也可以得到数据

    5、UDP三种通信方式

    5.1、单播:

    • 一对一发送
    • 之前写的代码就是单播通信

    5.2、组播

    • 一对多发送,但是多个接收端要是一组的

    • 代码实现

    组播地址:244.0.0.0 ~ 244.255.255.255 。其中244.0.0.0 ~ 244.0.0.255是预留的组播地址

    
    

    5.3、广播

    • 一对所有发送

    • 代码实现

    六、TCP通信程序

    1、TCP通信原理

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

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

    • 通过socket产生IO流来进行通信

    2、TCP发送数据的步骤

    ①、创建客户端Socket对象,与指定的服务端连接

    ②、获取输出流,写出数据

    ③、释放资源

    • 代码实现如下
    public class ClientDemo {
        public static void main(String[] args) throws IOException {
    
            Socket socket = new Socket("127.0.0.1", 10000);
    
            OutputStream os = socket.getOutputStream();
            os.write("xian".getBytes());
    
            os.close();
            socket.close();
        }
    }
    
    //注意:此时如果我们运行,是会报异常ConnectException,因为无法和接收端建立连接
    

    3、TCP接受数据

    ①、创建服务端Socket对象(ServerSocket)

    ②、监听客户端,返回一个Socket对象

    ③、获取输入流,读数据,把数据显示在控制台

    ④、释放资源

    • 代码实现
    public class ServerDemo {
        public static void main(String[] args) throws IOException {
    
            ServerSocket ss = new ServerSocket(10000);
    
            System.out.println(111);
            Socket accept = ss.accept();//等待客户端来进行连接,一直等待
            System.out.println(222);
    
            //复习
            InputStream is = accept.getInputStream();
            int b;
            while ((b = is.read() )!= -1){
                System.out.println((char) b);
            }
            
            is.close();
            ss.close();
        }
    }
    

    4、原理分析

    • 需要先运行服务端,服务端会执行到 ss.accept()处等待客户端连接
    • 客户端连接,发送数据
    • 服务端接受收据

    注意

    • accept()方法是阻塞的,作用:等待客户端连接
    • 客户端连接服务器通过:三次握手

    下面的类比就尼玛离谱,公平打在有才上

    • 针对客户端,往外写,用输出流;针对服务端,往里读,用输入流
    • read()方法是阻塞的
    • os.close()会附带一个结束标记,来让read结束
    • socket.close()关闭连接通过:四次挥手

    5、练习一

    客户端:发送数据,接受服务端反馈

    服务端:接收数据,给出反馈

    客户端代码

    public class ClientDemo {
        public static void main(String[] args) throws IOException {
            //创建socket对象
            Socket socket = new Socket("127.0.0.1", 10086);
    
            //获取输出流,写出数据
            OutputStream os = socket.getOutputStream();
            os.write("hello".getBytes());
            socket.shutdownOutput();//关闭输出流,写一个结束标记给接收端,不会关闭socket
    
            //获取输入流,读入数据
            /*
            InputStream is = socket.getInputStream();
            int b;
            while ((b = is.read()) != -1){
                System.out.println((char) b);
            }
            */
            //因为接受的是中文,用字节流会乱码,socket又没有字符流,--->用缓冲流
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String line;
            while ((line = br.readLine()) != null){
                System.out.println(line);
            }
    
            //关闭资源
            br.close();
            os.close();
            socket.close();
    
        }
    }
    

    服务端代码

    public class ServerDemo {
        public static void main(String[] args) throws IOException {
            //创建socket对象
            ServerSocket ss = new ServerSocket(10086);
    
            //监听客户端,返回一个Socket对象
            Socket accept = ss.accept();
    
            //获取输入流,读入数据
            InputStream is = accept.getInputStream();
            int b;
            while ((b = is.read()) != -1){
                System.out.println((char) b);
            }
    
            //获取输出流,写出数据
            /*OutputStream os = accept.getOutputStream();
            os.write("你谁啊".getBytes());*/
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
            bw.write("你谁啊?");
    
            //关闭资源
            bw.close();
            is.close();
            ss.close();
        }
    }
    

    6、练习二

    客户端:将文件上传到服务器,接受服务器的反馈

    服务器:接受客户端上传的文件,上传完毕后给出反馈

    客户端代码

    public class ClientDemo {
        public static void main(String[] args) throws IOException {
            //创建socket
            Socket socket = new Socket("127.0.0.1", 10086);
    
            //本地流,读取本地文件
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("heima/ClientDir/java图标.jpg"));
    
            //网络中的流,写到服务器
            OutputStream os = socket.getOutputStream();
            BufferedOutputStream bos = new BufferedOutputStream(os);
    
            int b;
            while ((b = bis.read()) != -1){
                bos.write(b);
            }
    
            socket.shutdownOutput();//给服务器一个结束标记,表名传输完毕
    
            //获取服务端数据
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String line;
            while ((line = br.readLine()) != null){
                System.out.println(line);
            }
    
            //关闭资源
            socket.close();
            bis.close();
        }
    }
    

    服务端代码

    public class ServerDemo {
        public static void main(String[] args) throws IOException {
    
            //创建socket
            ServerSocket ss = new ServerSocket(10086);
            //等待连接
            Socket accept = ss.accept();
    
            //网络中的流,读取客户端数据
            BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());
            //本地的流,持久化
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("heima/ServerDir/copy.jpg"));
            //读取,持久化到本地
            int b;
            while ((b = bis.read()) != -1){
                bos.write(b);
            }
    
            //发送反馈信息
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
            bw.write("上传成功");
            bw.newLine();
            bw.flush();
    
            //关闭资源
            ss.close();
            accept.close();//网络中的流,随着socket的关闭也会关闭
            bos.close();
        }
    }
    
  • 相关阅读:
    剑指Offer面试题:26.字符串的排列
    剑指Offer面试题:25.二叉搜索树与双向链表
    使用VS2013分析DMP文件
    目的 存在 问题 价值
    thinking models--基于事实和全方位思考
    目的-哲学解释
    亚里士多德.四因说
    存在与目的 人类与上帝
    我用过的数据库 sqlite realm mysql coredata
    swift Existential Container witness table
  • 原文地址:https://www.cnblogs.com/liuzhixian666/p/14353485.html
Copyright © 2020-2023  润新知