zoukankan      html  css  js  c++  java
  • 18.网络编程

    网路编程入门

    网络编程概述

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

    image-20201022174238963

    网络编程

    • 在网络通信写一下, 实现网络互连的不同计算机上运行的程序间可以进行数据交换.

    网络编程三要素

    ip地址:

    • 计算机在网络中的标志号, 用于找到改计算机

    端口

    • 网络通信, 本质上是两个应用程序通信. 端口号就是计算机上用来唯一标识设备中的应用程序.

    协议

    • 同一个网络的计算机连接和通讯时需要遵守一定的规则.称为网络通信协议, 对数据的传输格式, 传输速率, 传输步骤做了统一的规则, 必须同时遵守,才能完成数据交换. 常见UDP和TCP

    IP地址

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

    IP地址分类:

    • IPV4: 给连接在网络上的每一台主机分配一个32bit的地址, 按照TCP/IP堆顶, 使用二进制表示,每个长32bit, 也就是4个字节. 一般用"点分十进制表示", 如"192.168.1.66"

    • IPV6: 为了扩大地址空间, 重新定义IPV6规则, 采用128位地址长度, 分成8组,每组16个字节

    查看命令

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

    InetAddress类

    为了方便对IP地址的获取和操作, java提供了一个类InetAddress供使用

    InetAddress: 此类表示Internet协议(IP)地址

    方法名 说明
    Static InetAddress getByName(String host) 确定主机名的IP地址, 主机名可以是机器名称, 也可以是IP地址
    String getHostName() 获取此IP地址的主机名
    String getHostAddress() 返回文本显示中的IP地址字符串

    Demo

    package netProgram;
    
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    public class inetAddress {
        public static void main(String[] args) throws UnknownHostException {
            // Static InetAddress getByName(String host): 确定主机名的IP地址, 主机名可以是机器名称, 也可以是IP地址
            // InetAddress address = InetAddress.getByName("mac");
            InetAddress address = InetAddress.getByName("192.168.110.47");
    
            // String getHostName(): 获取此IP地址的主机名
            String name = address.getHostName();
    
            // public String getHostAddress(): 返回文本显示中的IP地址字符串
            String ip = address.getHostAddress();
    
            System.out.println("主机名:" + name);
            System.out.println("IP地址:" + ip);
        }
    
    }
    
    

    端口

    端口是设备上应用程序的唯一标识

    用两个字节表示的整数, 取值范围是0~65535. 其中, 0~1023之间的端口用于一些知名网络服务和应用. 端口占用会导致程序启动失败.

    协议

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

    UDP协议:

    • 用户数据报协议(User Datagram Protocal)
    • 无连接通信协议, 消耗小, 通信效率高, 用于音频, 视频和普通数据的传输

    TCP协议:

    • 传输控制协议(Transminssion Control Protocal)

    • 面向连接的通信协议, 提供可靠无差错的数据传输. 必须明确客户端与服务器端, 有客户端向服务器发出连接请求, 每次连接经过"三次握手", 端口经过"四次挥手".

    UDP通信原理

    UDP是一种不可靠协议, 在通信两端个建立一个Socket对象, 但是这两个Socket只是发送, 接受数据的对象.

    Java提供了DatagramSocket类作为基于UDP协议的socket

    UDP发送数据

    Demo

    package netProgram;
    
    import java.io.IOException;
    import java.net.*;
    
    public class UDPSendDemo {
        public static void main(String[] args) throws IOException {
            // 创建发送端的Socket对象(DatagramSocket)
            // DatagramSocket(): 构造数据报套接字并将其绑定到本地主机的任何可用端口
            DatagramSocket ds = new DatagramSocket();
    
            // 创建数据,并打包
            // DatagramPacket (byte[] buf, int length, InetAddress address, int port): 构造一个数据包, 发送长度为length的数据报到指定主机上的指定端口
            byte[] bys = "hello, i am comming".getBytes();
            // int length = bys.length;
            // InetAddress address = InetAddress.getByName("mac");
            // int port = 10086;
            // DatagramPacket dp = new DatagramPacket(bys, length, address, port);
            DatagramPacket dp = new DatagramPacket(bys, bys.length, InetAddress.getByName("mac"), 10086);
    
            // 调用DatagramSocket发送数据的方法
            // void send(DatagramPacket p) 从此套接字发送数据报包
            ds.send(dp);
    
            // 关闭发送端
            ds.close();
        }
    }
    
    

    UDP接受数据

    Demo

    package netProgram;
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    
    public class UDPRecvDemo {
        public static void main(String[] args) throws IOException {
            // 创建发送端的Socket对象(DatagramSocket)
            // DatagramSocket(int port): 构造数据报套接字并将其绑定到本地主机的指定端口
            DatagramSocket ds = new DatagramSocket(10086);
    
            // 创建数据包, 接受数据
            // DatagramPacket (byte[] buf, int length): 构造一个数据包,用于接受长度length数据报
            byte[] bys = new byte[1024];
            DatagramPacket dp = new DatagramPacket(bys, bys.length);
    
            // 调用DatagramSocket接受数据的方法
            // void receive(DatagramPacket p) 从此套接字接收数据报包
            ds.receive(dp);
    
            // 解析数据包
            // byte[] getData(): 返回数据缓冲区数据
            byte[] data = dp.getData();
            // int getLength(): 获取返回数据的长度
            int len = dp.getLength();
            String dataString = new String(data, 0, len);
            System.out.println("数据是:" + dataString);
    
            // 关闭发送端
            ds.close();
        }
    }
    
    

    UDP通信案例

    UDPSendDemo

    package netProgram.correspondence;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    
    public class UDPSendDemo {
        public static void main(String[] args) throws IOException {
            // 创建socket对象
            DatagramSocket ds = new DatagramSocket();
    
            // 自己封装键盘录入数据
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String line;
            while ((line=br.readLine())!=null) {
                if ("886".equals(line)) {
                    break;
                }
                // 创建数据并打包
                byte[] bys = line.getBytes();
                DatagramPacket dp = new DatagramPacket(bys,bys.length, InetAddress.getByName("mac"), 12345);
    
                // 发送数据
                ds.send(dp);
            }
            // 关闭
            ds.close();
        }
    }
    

    UDPRecvDemo

    package netProgram.correspondence;
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.SocketException;
    
    public class UDPRecvDemo {
        public static void main(String[] args) throws IOException {
            // 创建socket对象
            DatagramSocket ds = new DatagramSocket(12345);
    
            while (true) {
                // 创建数据包接收数据
                byte[] bys = new byte[1024];
                DatagramPacket dp = new DatagramPacket(bys, bys.length);
    
                // 接收数据
                ds.receive(dp);
    
                // 解析数据包, 并把数据在控制台显示
                System.out.println("数据:" + new String(dp.getData(),0, dp.getLength()));
            }
    
        }
    }
    
    

    TCP通信原理

    TCP通信是一种可靠的网络协议, 他在通信两端各建立一个Socket对象, 从而在通信的两端形成网络虚拟链路, 一旦建立虚拟的网络链路, 两端的程序可以通过虚拟链路进行通信

    Java对TCP协议的网络进行了封装, 使用Socket对象来代表两端的通信端口, 通过Socket产生IO流来进行网络通信

    TCP发送数据

    发送数据步骤

    1. 创建客户端Socket对象(Socket)
    2. 获取输出流, 写数据
    3. 释放资源

    TCPClientDemo

    package netProgram.tcp;
    
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.InetAddress;
    import java.net.Socket;
    
    public class TCPClientDemo {
        public static void main(String[] args) throws IOException {
            // 创建Socket对象
            // Socket(InetAddress address, int port): 创建流套接字并将其连接到指定IP地址的指定端口
            // Socket s = new Socket(InetAddress.getByName("mac"), 10000);
    
            // Socket(String host, int port): 创建流套接字并将其连接到指定IP地址的指定端口
            Socket s = new Socket("192.168.110.47", 10000);
    
            // 获取输出流, 写数据
            // OutputStream getOutputStream() 返回此套接字的输出流
            OutputStream os = s.getOutputStream();
            os.write("hello, tcp, i am comming".getBytes());
    
            // 释放资源
            s.close();
        }
    }
    
    

    TCP接收数据

    接受数据步骤

    1. 创建服务器端的Socket对象(ServerSocket)
    2. 监听客户端连接, 返回一个Socket对象
    3. 获取输入流, 读数据, 并把数据显示在控制台
    4. 释放资源

    TCPServerDemo

    package netProgram.tcp;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TCPServerDemo {
        public static void main(String[] args) throws IOException {
            // 创建服务器端的Socket对象(ServerSocket)
            // ServerSocket​(int port): 创建绑定到指定端口的服务器套接字
            ServerSocket ss = new ServerSocket(10000);
    
            // Socket accept(): 侦听对此套接字的连接并接受它
            Socket s = ss.accept();
    
            // 获取输入流, 读数据, 并且将数据显示在控制台
            InputStream is = s.getInputStream();
            byte[] bys = new byte[1024];
            int len = is.read(bys);
            String data = new String(bys, 0, len);
            System.out.println("数据:" + data);
    
            // 释放资源
            s.close();
            ss.close();
        }
    }
    
    

    TCP通信案例

    TCPClientDemo

    package netProgram.correspondence;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    
    public class TCPClientDemo {
        public static void main(String[] args) throws IOException {
            // 创建客户端Socket对象(Socket)
            Socket s = new Socket("192.168.110.47", 10000);
    
            // 获取输出流,写数据
            OutputStream os = s.getOutputStream();
            os.write("hello, tcp, i am comming".getBytes());
    
            // 接收服务器反馈
            InputStream is = s.getInputStream();
            byte[] bys = new byte[1024];
            int len = is.read(bys);
            String data = new String(bys, 0, len);
            System.out.println("客户端:" + data);
    
            // 释放资源
            s.close();  // 会关闭 is, os 资源
    
        }
    
    }
    
    

    TCPServerDemo

    package netProgram.correspondence;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TCPServerDemo {
        public static void main(String[] args) throws IOException {
            // 创建服务器端的Socket对象(ServerSocket)
            ServerSocket ss = new ServerSocket(10000);
            // 监听客户端连接, 返回一个Socket对象
            Socket s = ss.accept();
    
            // 获取输入流, 读数据, 并把数据显示在控制台
            InputStream is = s.getInputStream();
            byte[] bys = new byte[1024];
            int len = is.read(bys);
            String data = new String(bys, 0, len);
            System.out.println("服务器:" + data);
    
            // 给出反馈
            OutputStream os = s.getOutputStream();
            os.write("数据已经收到".getBytes());
    
            // 释放资源
            // s.close();
            ss.close();  // 这一步也会关闭s
        }
    
    }
    
    

    案例二: 字符流实现

    TCPClientDemo

    package netProgram.TCPCorrespondence;
    
    import java.io.*;
    import java.net.Socket;
    
    public class TCPClientDemo {
        public static void main(String[] args) throws IOException {
            // 创建客户端Socket对象
            Socket s = new Socket("192.168.110.47", 10000);
    
            // 数据来自键盘输入
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            // 封装输出流对象
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            String line;
            while ((line=br.readLine())!=null){
                if ("886".equals(line)){
                    break;
                }
                // 获取输出对象流
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
    
            // 释放资源
            s.close();
        }
    }
    
    

    TCPServerDemo

    package netProgram.TCPCorrespondence;
    
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TCPServerDemo {
        public static void main(String[] args) throws IOException {
            // 创建服务器端的Socket对象(ServerSocket)
            ServerSocket ss = new ServerSocket(10000);
            // 监听客户端连接, 返回一个Socket对象
            Socket s = ss.accept();
    
            // 获取输入流, 读数据, 并把数据显示在控制台
            BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
            String line;
            while ((line=br.readLine())!=null) {
                System.out.println(line);
            }
    
            // 释放资源
            // s.close();
            ss.close();  // 这一步也会关闭s
        }
    
    }
    

    案例三: 接受数据写入文本

    TCPClientDemo一致

    TCPServerDemo

    package netProgram.TCPCorrespondence.demo2;
    
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TCPServerDemo {
        public static void main(String[] args) throws IOException {
            // 创建服务器端的Socket对象(ServerSocket)
            ServerSocket ss = new ServerSocket(10000);
            // 监听客户端连接, 返回一个Socket对象
            Socket s = ss.accept();
    
            // 获取输入流, 读数据, 并把数据显示在控制台
            BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
            BufferedWriter bw = new BufferedWriter(new FileWriter("learn_java/tcp.txt"));
            String line;
            while ((line=br.readLine())!=null) {
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
    
            // 释放资源
            // s.close();
            bw.close();
            ss.close();  // 这一步也会关闭s
        }
    
    }
    
    

    案例四: 客户端数据来自文件, 服务器写入文本

    TCPClientDemo

    package netProgram.TCPCorrespondence.demo3;
    
    import java.io.*;
    import java.net.Socket;
    
    public class TCPClientDemo {
        public static void main(String[] args) throws IOException {
            // 创建客户端Socket对象
            Socket s = new Socket("192.168.110.47", 10000);
    
            // 封装文本文件的数据
            BufferedReader br = new BufferedReader(new FileReader("learn_java/tcp.txt"));
            // 封装输出流对象
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            String line;
            while ((line=br.readLine())!=null){
                // 获取输出对象流
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
    
            // 释放资源
            br.close();
            s.close();
        }
    }
    

    TCPServerDemo

    package netProgram.TCPCorrespondence.demo3;
    
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TCPServerDemo {
        public static void main(String[] args) throws IOException {
            // 创建服务器端的Socket对象(ServerSocket)
            ServerSocket ss = new ServerSocket(10000);
            // 监听客户端连接, 返回一个Socket对象
            Socket s = ss.accept();
    
            // 获取输入流, 读数据, 并把数据显示在控制台
            BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
            BufferedWriter bw = new BufferedWriter(new FileWriter("learn_java/tcp_server.txt"));
            String line;
            while ((line=br.readLine())!=null) {
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
    
            // 释放资源
            // s.close();
            bw.close();
            ss.close();  // 这一步也会关闭s
        }
    
    }
    
    

    案例五: 上传文件, 并反馈

    TCPClientDemo

    package netProgram.TCPCorrespondence.demo4;
    
    import java.io.*;
    import java.net.Socket;
    
    public class TCPClientDemo {
        public static void main(String[] args) throws IOException {
            // 创建客户端Socket对象
            Socket s = new Socket("192.168.110.47", 10000);
    
            // 封装文本文件的数据
            BufferedReader br = new BufferedReader(new FileReader("learn_java/tcp.txt"));
            // 封装输出流对象
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            String line;
            while ((line=br.readLine())!=null){
                // 获取输出对象流
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
            // 自定义结束标记
            /*
            bw.write("886");
            bw.newLine();
            bw.flush();
             */
    
            // 使用java提供的停止方法
            // public void shutdownOutput
            s.shutdownOutput();
    
            // 接受反馈
            BufferedReader brClient = new BufferedReader(new InputStreamReader(s.getInputStream()));
            String data = brClient.readLine();  // 等待服务器响应
            System.out.println("响应:" + data);
    
            // 释放资源
            br.close();
            s.close();
        }
    }
    

    TCPServerDemo

    package netProgram.TCPCorrespondence.demo4;
    
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TCPServerDemo {
        public static void main(String[] args) throws IOException {
            // 创建服务器端的Socket对象(ServerSocket)
            ServerSocket ss = new ServerSocket(10000);
            // 监听客户端连接, 返回一个Socket对象
            Socket s = ss.accept();
    
            // 获取输入流, 读数据, 并把数据显示在控制台
            BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
            BufferedWriter bw = new BufferedWriter(new FileWriter("learn_java/tcp_server.txt"));
            String line;
            while ((line=br.readLine())!=null) {  // 一直在等待读取数据
                /*
                if("886".equals(line)){
                    break;
                }
                 */
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
            // 给出反馈
            BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            bwServer.write("文件上传成功");
            bwServer.newLine();
            bwServer.flush();
    
            // 释放资源
            // s.close();
            bw.close();
            ss.close();  // 这一步也会关闭s
        }
    
    }
    

    案例六: 多线程上传文件

    ServerThread

    package netProgram.TCPCorrespondence.demo5;
    
    import java.io.*;
    import java.net.Socket;
    
    public class ServerThread implements Runnable {
        private Socket s;
        public ServerThread(Socket s) {
            this.s = s;
        }
    
        @Override
        public void run() {
            // 接受数据写入文件
            try {
                BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
                // BufferedWriter bw = new BufferedWriter(new FileWriter("learn_java/tcp_server5.txt"));
                // 处理名称冲突问题
                int count = 0;
                File file = new File("learn_java/tct_server" + count + ".txt");
                while (file.exists()) {
                    count++;
                    file = new File("learn_java/tct_server" + count + ".txt");
                }
                BufferedWriter bw = new BufferedWriter(new FileWriter(file));
    
                String line;
                while ((line=br.readLine())!=null) {
                    bw.write(line);
                    bw.newLine();
                    bw.flush();
                }
                // 给出反馈
                BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
                bwServer.write("文件上传成功");
                bwServer.newLine();
                bwServer.flush();
    
                // 释放资源
                s.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    

    TCPClientDemo

    package netProgram.TCPCorrespondence.demo5;
    
    import java.io.*;
    import java.net.Socket;
    
    public class TCPClientDemo {
        public static void main(String[] args) throws IOException {
            // 创建客户端Socket对象
            Socket s = new Socket("192.168.110.47", 10000);
    
            // 封装文本文件的数据
            BufferedReader br = new BufferedReader(new FileReader("learn_java/tcp.txt"));
            // 封装输出流对象
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            String line;
            while ((line=br.readLine())!=null){
                // 获取输出对象流
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
    
            // 使用java提供的停止方法
            // public void shutdownOutput
            s.shutdownOutput();
    
            // 接受反馈
            BufferedReader brClient = new BufferedReader(new InputStreamReader(s.getInputStream()));
            String data = brClient.readLine();  // 等待服务器响应
            System.out.println("响应:" + data);
    
            // 释放资源
            br.close();
            s.close();
        }
    }
    
    

    TCPServerDemo

    package netProgram.TCPCorrespondence.demo5;
    
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TCPServerDemo {
        public static void main(String[] args) throws IOException {
            // 创建服务器端的Socket对象(ServerSocket)
            ServerSocket ss = new ServerSocket(10000);
            while (true){
                // 监听客户端连接, 返回一个Socket对象
                Socket s = ss.accept();
                // 为每个客户端开启一个线程
                new Thread(new ServerThread(s)).start();
            }
        }
    
    }
    
    
  • 相关阅读:
    Android Service 与 Activity使用Pending Intent通信
    Android四大组件之Service(一)
    Android中的进程和线程
    Java虚拟机结构(二)
    Java虚拟机结构(一)
    Android四大组件之Activity(一)
    一阶规则学习
    规则学习
    算法链接
    41. First Missing Positive
  • 原文地址:https://www.cnblogs.com/ryxiong-blog/p/13890464.html
Copyright © 2011-2022 走看看