2021.07.23 Java学习笔记之网络编程

本文详细阐述了网络编程与网页编程的区别,包括它们各自的关注点、协议、IP地址、端口、URL等核心概念。通过Java实例展示了如何进行IP查找、端口操作、URL解析以及Socket通信。此外,还探讨了网络爬虫的基本流程和TCP/UDP套接字通信,并提供了客户端和服务端的登录示例,涵盖了多线程服务端的实现。
摘要由CSDN通过智能技术生成

网页编程和网络编程的区别

        网页编程:上层的应用,

        网络编程:底层,关注数据如何传输,如何存储

                节点:网络电子设备

                        节点和节点之间组成网络

                IP :表示节点

                端口:区分不同的软件

                URL :互联网中资源的指针,统一资源定位符

                协议:合同,规范,标准

                传输层协议:

                        UDP :相当于写信,只管写只管发,效率高,但是不安全 ,传输数据的大小存在限制。

                        TCP: 相当于打电话,面向连接,安全性高,效率低,传输数据的大小没有限制

                IP:定义网络中的节点(网络电子设备,手机,电脑,路由器。。。。)

                        分为:IPV4(4个字节,32位) IPV6(128位)

                        特殊IP:192.168.0.0~192.168.255.255  非注册IP,供组织内部使用
                                    127.0.0.1 本地IP
                                    localhost : 本地域名
                                    域名与IP之间的关系:  DNS解析器

java.net包
        InetAddress  类表示Internet协议(IP)地址

public static void main(String[] args) throws UnknownHostException {
        //static InetAddress getByName(String host) 根据主机名称确定主机的IP地址。
        //static InetAddress getLocalHost() 返回本地主机的地址。
        InetAddress address1 = InetAddress.getLocalHost();
        System.out.println(address1); //DESKTOP-KHNV6UD/192.168.16.236
        System.out.println(address1.getHostName());
        System.out.println(address1.getHostAddress());

        InetAddress address2 =  InetAddress.getByName("www.baidu.com");
        System.out.println(address2);
        System.out.println(address2.getHostName());
        System.out.println(address2.getHostAddress());
    }

端口:区分软件

        端口号 2个字节  0~65535
        同一协议下端口号不能冲突
        建议使用8000以上的,8000以下称为预留端口好 

        常见的端口:
               80 : http
                8080 : tomcat
                1521 : Oracle
               3306  : Mysql

  InetSocketAddress 此类实现IP套接字地址(IP地址+端口号)它也可以是一对(主机名+端口)

public static void main(String[] args)  {
        //InetSocketAddress(String hostname, int port) 根据主机名和端口号创建套接字地址。
        //InetSocketAddress(InetAddress addr, int port) 根据IP地址和端口号创建套接字地址。
        InetSocketAddress in = new InetSocketAddress("localhost",8989);
        System.out.println(in);
        System.out.println(in.getHostName());
        System.out.println(in.getPort());
    }

URL        

         同一资源定位符,指向万维网上的“资源”的指针。 

        组成:
                协议: http
                域名: www.baidu.com
                端口号: 80
                资源: index.html
                    提交数据: name=zhangsan&pwd=123
                    锚点: #a

            互联网 的三大基石:
                html
                http
                url

 public static void main(String[] args) throws MalformedURLException {
        //URL(String spec) 从 String表示创建 URL对象。
        //URL(String protocol, String host, int port, String file)
        URL url = new URL("https://www.baidu.com:80/index.html?name=zhangsan&pwd=123#a");

        System.out.println(url);
        System.out.println("协议:"+url.getProtocol());
        System.out.println("域名:"+url.getHost());
        System.out.println("端口:"+url.getPort());
        System.out.println("资源:"+url.getFile());
        System.out.println("资源:"+url.getPath());
        System.out.println("资源:"+url.getQuery());
        System.out.println("资源:"+url.getRef());
    }

  网络爬虫

 

public static void main(String[] args) throws IOException {
        //1.定义URL
        URL url = new URL("https://www.baidu.com/index.html");
        //2.获取流 : InputStream openStream() 打开与此 URL的连接并返回 InputStream以从该连接读取。
        InputStream is = url.openStream();
        //InputStreamReader 字节输入流转位字符输入流的节点流-->功能流
        BufferedReader rd = new BufferedReader(new InputStreamReader(is));
        String msg = null;
        //3.读入操作
        while((msg = rd.readLine())!=null){
            System.out.println(msg);
        }
        //4.关闭
        rd.close();
        is.close();
    }

套接字 

        传输层为应用层开配的小口子

        不同协议下的Socket实现不同

         UDP : 相当于写信|有包裹|发短信  非面向连接   协议简单,开销小,效率高   不安全    大小由限制(一般不超过60k)
        TCP : 相当于打电话       面向连接    效率低  安全      大小没有限制 基于三次握手

         UDP协议下发送端和接收端两端平等 

                DatagramSocket  此类表示用于发送和接收数据报包的套接字。
                DatagramSocket(int port) 构造一个数据报套接字并将其绑定到本地主机上的指定端口。
                void receive(DatagramPacket p) 从此套接字接收数据报包。
                void send(DatagramPacket p) 从此套接字发送数据报包。

        DatagramPacket 该类表示数据报包。
                    byte[] getData() 返回数据缓冲区。
                    int getLength() 返回要发送的数据的长度或接收的数据的长度。 

数据的传输基于字节数组 

 UDP实现发送端: 基本流程
            1.定义我是发送端
            2.准备数据
            3.打包
            4.发送
            5.关闭

 public static void main(String[] args) throws IOException {
            // 1.定义我是发送端
            DatagramSocket s = new DatagramSocket(9090);

            System.out.println("-------------我是发送端-------------");

            // 2.准备数据
            byte[] arr = "你好".getBytes();
            // 3.打包
            DatagramPacket packet = new DatagramPacket(arr,0,arr.length,new InetSocketAddress("127.0.0.1",8989));
            // 4.发送
            s.send(packet);
            // 5.关闭
            s.close();
        }

UDP实现接收端: 基本流程
        1.定义我是接收端
        2.准备字节数组,打包
        3.接收数据
        4.处理数据
        5.关闭

注意;  统一协议下端口号不能冲突

 

ublic static void main(String[] args) throws IOException {
        //1.定义我是接收端
        DatagramSocket r = new DatagramSocket(8989);

        System.out.println("-----------我是接收端------------");

        //2.准备字节数组,打包
        byte[] arr = new byte[1024];
        DatagramPacket packet = new DatagramPacket(arr,arr.length);
        //3.接收数据
        r.receive(packet);
        //4.处理数据
        //byte[] getData() 返回数据缓冲区。
        //int getLength() 返回要发送的数据的长度或接收的数据的长度。
        byte[] newArr = packet.getData();
        int len = packet.getLength();

        System.out.println(new String(newArr,0,len));

        //5.关闭
        r.close();
    }

客户端  Socket

        Socket(String host, int port) 创建流套接字并将其连接到指定主机上的指定端口号。
        InputStream getInputStream()
        OutputStream getOutputStream()
    服务器  ServerSocket 该类实现服务器套接字。
        ServerSocket(int port) 创建绑定到指定端口的服务器套接字。
        Socket accept() 侦听对此套接字的连接并接受它。

 TCP 协议下传输数据基于IO流

        客户端的实现基本流程:

                1.定义我是客户端-->指定要请求的服务器的IP+端口
​                2.准备数据
​                3.获取输出流
​                4.输出-->IO操作
​                5.刷出
​                6.关闭

ublic static void main(String[] args) throws IOException {
​        System.out.println("-----------我是客户端--------------");
​        //  1.定义我是客户端-->指定要请求的服务器的IP+端口
​        Socket client = new Socket("localhost",9999);
​        System.out.println("-----------与服务器端建立连接--------------");
​        //  2.准备数据
​        String str = "你好";
​        //  3.获取输出流
​        DataOutputStream os = new DataOutputStream(new BufferedOutputStream(client.getOutputStream()));
​        //  4.输出-->IO操作
​        os.writeUTF(str);
​        //  5.刷出
​        os.flush();
​        //  6.关闭
​        os.close();
​        client.close();
​    }

 tcp协议实现基本流程 : 服务端
        1.定义我是服务端
        2.阻塞式监听
        3.获取输入流-->接收客户端的请求数据
        4.处理数据
        5.关闭

 

public static void main(String[] args) throws IOException {
        System.out.println("-----------我是服务器端-----------");
        // 1.定义我是服务端
        ServerSocket server = new ServerSocket(9999);
        // 2.阻塞式监听
        Socket client = server.accept();

        System.out.println("-----------一个客户端连接成功----------");

        // 3.获取输入流-->接收客户端的请求数据
        DataInputStream is = new DataInputStream(new BufferedInputStream(client.getInputStream()));
        String msg = is.readUTF();
        // 4.处理数据
        System.out.println(msg);
        // 5.关闭
        is.close();
        client.close();
        server.close();
    }

TCP 单向登录: 客户端和服务端

public static void main(String[] args) throws IOException {
        System.out.println("-------我是客户端---------");
        //1.定义客户端
        Socket client = new Socket("localhost",9898);
        //2.准备数据(用户输入)
        //    1)输入流
        BufferedReader rd = new BufferedReader(new InputStreamReader(System.in));
        //    2)用户名与密码
        System.out.println("请输入用户名");
        String username = rd.readLine();
        System.out.println("请输入密码");
        String password = rd.readLine();
        System.out.println(username+"-->"+password);
        //3.获取输出流向服务器端发送数据(用户名与密码)
        DataOutputStream os = new DataOutputStream(client.getOutputStream());
        //username=laopei&password=1234
        os.writeUTF("username="+username+"&password="+password);
        //4.刷出
        os.flush();
        //5.关闭
        os.close();
        rd.close();
        client.close();
    }

 

public static void main(String[] args) throws IOException {
        System.out.println("--------我是服务器-------");
        //1.定义我是服务器
        ServerSocket server = new ServerSocket(9898);
        //2.阻塞式监听
        Socket client = server.accept();
        System.out.println("一个客户端连接成功........");
        //3.获取输入流接收客户端发动的数据
        DataInputStream is = new DataInputStream(client.getInputStream());
        String msg = is.readUTF();  //username=laopei&password=1234
        //4.处理数据
        System.out.println(msg);
        //5.关闭
        is.close();
        client.close();
        server.close();
    }

TCP 双向登录: 客户端和服务端

public static void main(String[] args) throws IOException {
        System.out.println("-------我是客户端---------");
        //1.定义客户端
        Socket client = new Socket("localhost",9898);
        //2.准备数据(用户输入)
        //    1)输入流
        BufferedReader rd = new BufferedReader(new InputStreamReader(System.in));
        //    2)用户名与密码
        System.out.println("请输入用户名");
        String username = rd.readLine();
        System.out.println("请输入密码");
        String password = rd.readLine();
        System.out.println(username+"-->"+password);
        //3.获取输出流向服务器端发送数据(用户名与密码)
        DataOutputStream os = new DataOutputStream(client.getOutputStream());
        //username=laopei&password=1234
        os.writeUTF("username="+username+"&password="+password);
        //4.刷出
        os.flush();

        //5.获取输入流 从服务器端读取响应
        DataInputStream is = new DataInputStream(client.getInputStream());
        System.out.println(is.readUTF());;

        //6.关闭
        is.close();
        os.close();
        rd.close();
        client.close();
    }

 

 public static void main(String[] args) throws IOException {
        System.out.println("--------我是服务器-------");
        //1.定义我是服务器
        ServerSocket server = new ServerSocket(9898);
        //2.阻塞式监听
        Socket client = server.accept();
        System.out.println("一个客户端连接成功........");
        //3.获取输入流接收客户端发动的数据
        DataInputStream is = new DataInputStream(client.getInputStream());
        String msg = is.readUTF();  //username=laopei&password=1234
        //4.处理数据
        System.out.println(msg);
        //处理1)
        /*String str = "username=laopei&password=1234";
        if(str.equals(msg)){
            System.out.println("登录成功");
        }else{
            System.out.println("登录失败");
        }*/

        //2)
        String username = null;
        String password = null;
        String[] strs = msg.split("&");
        for(String s:strs){
            String[] arr = s.split("=");
            if("username".equals(arr[0])){
                username = arr[1];
            }else if("password".equals(arr[0])){
                password = arr[1];
            }
        }

        //5.获取输出流 把结果响应 给客户端
        DataOutputStream os = new DataOutputStream(client.getOutputStream());

        if("laopei".equals(username) && "1234".equals(password)){
            os.writeUTF("登录成功");
        }else{
            os.writeUTF("登录失败");
        }

        //6.刷出
        os.flush();
        //7.关闭
        os.close();
        is.close();
        client.close();
        server.close();
    }

TCP 双向登录: 服务端(多线程实现)

        通过循环

public static void main(String[] args) throws IOException {
        System.out.println("--------我是服务器-------");
        //1.定义我是服务器
        ServerSocket server = new ServerSocket(9898);
        //2.阻塞式监听
        boolean flag = true;
        while(flag){
           Socket client = server.accept();
           System.out.println("一个客户端连接成功........");
           //3.获取输入流接收客户端发动的数据
           DataInputStream is = new DataInputStream(client.getInputStream());
           String msg = is.readUTF();
           //4.处理数据
           String username = null;
           String password = null;
           String[] strs = msg.split("&");
           for(String s:strs){
               String[] arr = s.split("=");
               if("username".equals(arr[0])){
                   username = arr[1];
               }else if("password".equals(arr[0])){
                   password = arr[1];
               }
           }

           //5.获取输出流 把结果响应 给客户端
           DataOutputStream os = new DataOutputStream(client.getOutputStream());

           if("laopei".equals(username) && "1234".equals(password)){
               os.writeUTF("登录成功");
           }else{
               os.writeUTF("登录失败");
           }

           //6.刷出
           os.flush();
           //7.关闭
           os.close();
           is.close();
           client.close();
       }
        server.close();
    }

多线程实现

public static void main(String[] args) throws IOException {
        System.out.println("--------我是服务器-------");
        //1.定义我是服务器
        ServerSocket server = new ServerSocket(9898);
        //2.阻塞式监听
        boolean flag = true;
        while(flag){
           Socket client = server.accept();
           System.out.println("一个客户端连接成功........");

           //开启线程为上面监听到客户端响应
            new Thread(new Channel(client)).start();

       }
        server.close();
    }

    static class Channel implements Runnable{
        private Socket client = null;
        private DataInputStream is = null;
        private  DataOutputStream os = null;

        public Channel(Socket client) {
            this.client = client;
            try {
                is = new DataInputStream(client.getInputStream());
                os = new DataOutputStream(client.getOutputStream());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        //读入数据
        public String read(){
            String msg = null;
            try {
                msg = is.readUTF();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return msg;
        }

        //写出
        public void write(String msg){
            try {
                os.writeUTF(msg);
                os.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        //关闭资源
        public void close(){
            if(os!=null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(is!=null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(client!=null){
                try {
                    client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }


        @Override
        public void run() {
            //获取输入流接收客户端发动的数据
            String msg = read();

            //处理数据
            String username = null;
            String password = null;
            String[] strs = msg.split("&");
            for(String s:strs){
                String[] arr = s.split("=");
                if("username".equals(arr[0])){
                    username = arr[1];
                }else if("password".equals(arr[0])){
                    password = arr[1];
                }
            }

            //获取输出流 把结果响应 给客户端
            if("laopei".equals(username) && "1234".equals(password)){
                write("登录成功");
            }else{
                write("登录失败");
            }

            //关闭
            close();
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值