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();
            }
        }
    
    }
    
    
  • 相关阅读:
    Python3之random模块常用方法
    Go语言学习笔记(九)之数组
    Go语言学习笔记之简单的几个排序
    Go语言学习笔记(八)
    Python3之logging模块
    Go语言学习笔记(六)
    123. Best Time to Buy and Sell Stock III(js)
    122. Best Time to Buy and Sell Stock II(js)
    121. Best Time to Buy and Sell Stock(js)
    120. Triangle(js)
  • 原文地址:https://www.cnblogs.com/ryxiong-blog/p/13890464.html
Copyright © 2011-2022 走看看