(day23) 网络编程

    
第一章 网络编程入门
    1.1 网络通信协议
        计算机进行数据传输  需要遵守的规则
    UDP协议特点
        面向无连接的通信协议  两台计算机进行数据交互不需要建立连接
        发送端直接给接收端发送数据  接收端接收到数据也不会给发送端回应
        
        UDP不需要建立连接 消耗资源少 发送速率快 但是每次发送数据不能超过64KB
        不能保证数据的完整性
        
    TCP协议特点
        面向连接的通讯协议 两天计算机要想进行数据交互必须进行连接
        客户端----> 服务端
        客户端<---- 服务端
        客户端----> 服务端
        
        建立连接 消耗资源多 发送速率慢  但是发送数据无限制  可以保证数据的可靠性
        
    1.2 网络编程三要素
        三要素:
        协议: 计算机网络通信必须遵守的规则
        IP地址: 指互联网协议地址(Internet Prottocol Address),俗称IP;
            IP地址是计算机进入到网络中的唯一标识
            
            IPv4: 四个字节大小的二进制数来表示  每个字节用一个十进制数字(0-255)表示, 数字用符号"."分开,如"192.168.1.100";
            IPv6: 采用128为地址长度, 每16个字节一组, 分成8组十六进制数, 表示成ABCD:EF01:2345:6789
            
            查看本机IP
                ipconfig
            监测两台计算机是否能够建立连接
                ping 网址/IP
            两个特殊的IP地址
                127.0.0.1
                localhost   本地主机/当前计算机的IP
        端口号: 用来表示应用程序, 用两个字节表示的整数, 它的取值范围是 0-65535.
        
    1.3 InetAddress
        java.bet.InetAddress
            静态方法
                static InetAddress getLocalHost();  返回本地主机
                static InetAddress getByName(String host);  在给定主机名的情况下确定主机的 IP 地址
                public String getHostName();   获取此 IP 地址的主机名。
                public String getHostAddress();   返回 IP 地址字符串(以文本表现形式)。
        代码演示:
        public static void main(String[] args) throws UnknownHostException {
            //获取本地主机
            InetAddress host = InetAddress.getLocalHost();
            System.out.println(host);

            String hostName = host.getHostName();
            String hostAddress = host.getHostAddress();
            System.out.println(hostName);
            System.out.println(hostAddress);

            System.out.println("---------------------------");
            InetAddress byName = InetAddress.getByName("192.169.5.7");
            System.out.println(byName);
            System.out.println(byName.getHostName());

            InetAddress byName1 = InetAddress.getByName("www.baidu.com");
            System.out.println(byName1);
        }
        结果:
            DESKTOP-AMHN57C/192.168.5.83
            DESKTOP-AMHN57C
            192.168.5.83
            ---------------------------
            /192.169.5.7
            192-169-5-7-static.despegar.net
            www.baidu.com/110.242.68.3
        
第三章 UDP通信

    3.1 发送端(发送端一定要明确指出数据的目的地(ip地址和端口号))
        java.net.DatagramSocket
            构造方法
                public DatagramSocket();
            方法
                void send(DatagramPacket p); 发送数据包
      发送端数据包
            java.net.DatagramPacket
                构造方法
                    public datagramPacket(byte[] bytes,int length, InetAddress ip, int port);
                    用来将长度为 length 的包发送到指定主机上的指定端口号
                        1. 创建发送端对象
                        2. 创建数据包对象  封装数据包
                        3. 调用发送端的send方法  发送数据包
                        4. 关闭资源
        (注: DatagramPacket数据包的作用就如同是“集装箱”,可以将发送端或者接收端的数据封装起来
        DatagramSocket类的作用就类似于码头,使用这个类的实例对象就可以发送和接收DatagramPacket数据包)
        代码演示:
        public static void main(String[] args) throws IOException {
            // 1. 创建发送端对象
            DatagramSocket ds = new DatagramSocket();
            //  2. 创建数据包对象  封装数据包
            byte[] bytes = "Hello, UDP!".getBytes();
            InetAddress ip = InetAddress.getByName("127.0.0.1");
            DatagramPacket dp = new DatagramPacket(bytes,bytes.length,ip,9999);
            // 3. 调用发送端的send方法  发送数据包
            ds.send(dp);
            //  4. 关闭资源
                ds.close();
        }
        
    3.2 接收端
        UDP接收端
        java.net.DategramSocket
            构造方法
                public DategramSocket(int port); 创建接收端对象 比并将其绑定到本地主机上的指定接口
            方法
                void receive(DatagramPacket p); 接收数据包

        接收端数据包
            java.net.DatagramPacket
                构造方法
                    DatagramPacket(byte[] buf, int length); 用来接收长度为 length 的数据包
                方法
                    InetAddress getAddress();  获取发送端IP地址
                    int getLength();  获取接受数据的长度
                    int getPort();  获取发送端断口

                    1. 创建接收端对象
                    2. 创建接收端数据包对象
                    3. 调用接收端的receive接受数据
                    4. 拆包
                    5. 关闭资源
        代码演示:
        public static void main(String[] args) throws IOException {
            // 1. 创建接收端对象
            DatagramSocket ds = new DatagramSocket(9999);
            // 2. 创建接收端数据包对象
            byte[] bytes = new byte[1024*64];
            DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
            // 3. 调用接收端的receive接受数据
            ds.receive(dp);
            // 4. 拆包
            InetAddress ip = dp.getAddress();
            int port = dp.getPort();
            int length = dp.getLength();

            System.out.println(ip+":"+port+" "+new String(bytes,0,length));
            // 5. 关闭资源
            ds.close();
        }
        
        模拟简单聊天室案例:
        代码演示:
        
        (发送端)
        import java.io.IOException;
        import java.net.*;
        import java.util.Scanner;
        public class Test02 {
            public static void main(String[] args) throws IOException {
                // 1. 创建发送端对象
                DatagramSocket ds = new DatagramSocket();
                //  2. 创建数据包对象  封装数据包
                Scanner sc = new Scanner(System.in);
                while(true){
                    String line = sc.nextLine();
                    byte[] bytes = line.getBytes();
                    InetAddress ip = InetAddress.getByName("127.0.0.1");
                    DatagramPacket dp = new DatagramPacket(bytes,bytes.length,ip,9999);
                    // 3. 调用发送端的send方法  发送数据包
                    ds.send(dp);
                }
                //  4. 关闭资源
                //  ds.close();
            }
        }
        
        (接收端)
        import java.io.IOException;
        import java.net.DatagramPacket;
        import java.net.DatagramSocket;
        import java.net.InetAddress;
        import java.net.SocketException;
        public class Test03 {
            public static void main(String[] args) throws IOException {
                // 1. 创建接收端对象
                DatagramSocket ds = new DatagramSocket(9999);
                // 2. 创建接收端数据包对象
                while(true){
                    byte[] bytes = new byte[1024*64];
                    DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
                    // 3. 调用接收端的receive接受数据
                    ds.receive(dp);
                    // 4. 拆包
                    InetAddress ip = dp.getAddress();
                    int port = dp.getPort();
                    int length = dp.getLength();
                    System.out.println(ip+":"+port+" "+new String(bytes,0,length));
                }
                // 5. 关闭资源
                // ds.close();
            }
        }
        
        结果:
        (发送数据):
        aaa
        bbb
        zxcasdqwe
        ertdfgcvb
        (接收数据):
        /127.0.0.1:56333 aaa
        /127.0.0.1:56333 bbb
        /127.0.0.1:56333 zxcasdqwe
        /127.0.0.1:56333 ertdfgcvb
        
第四章 TCP通信协议
    4.1 概述
        TCP通信能实现两台计算机之间的数据交互,通信的两端,要严格区分为客户端(Client)与服务端(Server)。
        两端通信时步骤:
            1. 服务端程序,需要事先启动,等待客户端的连接。
            2. 客户端主动连接服务器端,连接成功才能通信。服务端不可以主动连接客户端
        在Java中,提供了两个类用于实现TCP通信程序:

        客户端:java.net.Socket 类表示。
                创建 Socket 对象,向服务端发出连接请求,服务端响应请求,两者建立连接开始通信。
        服务端:java.net.ServerSocket 类表示。
                创建 ServerSocket 对象,相当于开启一个服务,并等待客户端的连接
        
    4.2 Socket类
        Socket 类:该类实现客户端套接字,套接字指的是两台设备之间通讯的端点
        
        java.net.Socket
            构造方法:
            Public Socket(String ip, int port);  创建客户端对象  连接服务端(该对象一旦创建,便自动连接服务端,若服务端不存在则报错)
            Public Socket(InetAddress ip, int port);  
            方法:
                InputStream getInputStream(); 获取字节输入流
                OutputStream getOutputStream(); 获取字节输出流
            过程:
            1. 创建客户端对象
            2. 获取字节输出流对象
            3. 向服务端 发送数据
            4. 获取字节输入流对象
            5. 接收服务端返回的数据
            6. 关闭资源
    
    4.3 ServerSocket类
        ServerSocket类:这个类实现了服务器套接字,该对象等待通过网络的请求。
        
        java.net.ServerSocket
        构造方法:
            public ServerSocket(int port); 创建服务端对象  绑定端口(参数port就是端口号)
        方法:
            Socket accept(); 获取正在连接的客户端对象
        过程:
        1. 创建服务端对象  绑定端口
        2. 调用accept方法 获取正在连接的客户端对象
        3. 使用客户端对象获取字节输入流对象
        4. 接收客户端发送的数据
        
        5. 使用客户端 获取字节输出流对象
        6. 向当前客户端 返回数据
        7. 关闭资源
        
    代码演示:
    
        (客户端)
        import java.io.IOException;
        import java.io.InputStream;
        import java.io.OutputStream;
        import java.net.Socket;
        public class Test004 {
            public static void main(String[] args) throws IOException {
                //  1. 创建客户端对象
                Socket s = new Socket("127.0.0.1",9999);
                //    2. 获取字节输出流对象
                OutputStream out = s.getOutputStream();
                //    3. 向服务端 发送数据
                out.write("你好,连一下呗".getBytes());

                System.out.println("-----------------------");
                //    4. 获取字节输入流对象
                InputStream in = s.getInputStream();
                //    5. 接收服务端返回的数据
                byte[] bytes = new byte[1024];
                int len = in.read(bytes);
                System.out.println(new String(bytes,0,len));
                //    6. 关闭资源
                s.close();
            }
        }
        
        (服务端)
        import java.io.IOException;
        import java.io.InputStream;
        import java.io.OutputStream;
        import java.net.ServerSocket;
        import java.net.Socket;
        public class Test005 {
            public static void main(String[] args) throws IOException {
                //  1. 创建服务端对象  绑定端口
                ServerSocket ss = new ServerSocket(9999);
                //    2. 调用accept方法 获取正在连接的客户端对象(accept方法具有阻塞功能,如果没有客户端连接, 服务端运行时会一直等待)
                Socket s = ss.accept();
                //    3. 使用客户端 获取字节输入流对象
                InputStream in = s.getInputStream();
                //    4. 接收客户端发送的数据
                byte[] bytes =new byte[1024];
                int len = in.read(bytes);
                System.out.println(new String(bytes,0,len));

                System.out.println("----------------------------------");
                //    5. 使用客户端 获取字节输出流对象
                OutputStream out = s.getOutputStream();
                //    6. 向当前客户端 返回数据
                out.write("滚,连你妹呀!!".getBytes());
                //    7. 关闭资源
                out.close();
                in.close();
                s.close();
                ss.close();
            }
        }
        结果:
        
        (接收端收到的客户端的信息)
        你好,连一下呗
        ----------------------------------
        
        (客户端收到的服务端返回的信息)
        -----------------------
        滚,连你妹呀!!
        
第五章 文件上传案例
        (文件只上传一次 ,如果想要实现多次上传,就要解决文件名相同的问题; 可以使用线程池(使用多线程)来解决)
    5.1 客户端实现
    
    数据源: D:\\2development\\abc\\zhaopian\\mm.jpg
    数据目的:服务端
    
    过程:
        1. 创建客户端对象 绑定服务端IP和端口
        2. 创建文件字节输出流  绑定数据源
        3. 获取字节输出流对象
        4. 循环读写
        
        5. 获取字节输入流对象
        6. 接收服务端返回的"上传成功"
        7. 关闭资源
        
    5.2 服务端实现
    
    数据源: 客户端
    数据目的: D:\\2development\\abc\\mm.jpg
    
    过程:
        1. 创建服务端对象  绑定端口号
        2. 调用accept方法 获取正在连接的客户端对象
        3. 获取字节输入流  用来接收客户端发送的数据
        4. 创建文件字节输出流 绑定数据目的
        5. 循环读写
        
        6. 获取字节输出流对象
        7. 向客户端返回数据"上传成功"
        8. 关闭资源
        
    5.3 代码演示:
    
        (客户端代码)
        import java.io.FileInputStream;
        import java.io.IOException;
        import java.io.InputStream;
        import java.io.OutputStream;
        import java.net.Socket;
        public class Test006 {
            public static void main(String[] args) throws IOException {
                //  1. 创建客户端对象 绑定服务端IP和端口
                Socket s = new Socket("127.0.0.1",6666);
                //    2. 创建文件字节输入流  绑定数据源
                FileInputStream fis = new FileInputStream("D:\\2development\\abc\\zhaopian\\mm.jpg");
                //    3. 获取字节输出流对象
                OutputStream out = s.getOutputStream();
                //    4. 循环读写
                byte[] bytes = new byte[1024];
                int len = 0;
                while((len = fis.read(bytes))!= -1){
                    out.write(bytes,0,len);
                }
                    //告知服务器已经写完了(相当于向服务端写过去一个结束标记)
                s.shutdownOutput();

                System.out.println("--------------接收服务端返回的数据----------------");
                //    5. 获取字节输入流对象
                InputStream in = s.getInputStream();
                //    6. 接收服务端返回的"上传成功"
                int length = in.read(bytes);
                System.out.println(new String(bytes,0,length));
                //    7. 关闭资源
                in.close();
                out.close();
                fis.close();
                s.close();
            }
        }
        
        (服务端代码)
        import java.io.FileOutputStream;
        import java.io.IOException;
        import java.io.InputStream;
        import java.io.OutputStream;
        import java.net.ServerSocket;
        import java.net.Socket;
        public class Test007 {
            public static void main(String[] args) throws IOException {
                //  1. 创建服务端对象  绑定端口号
                ServerSocket ss = new ServerSocket(6666);
                //    2. 调用accept方法 获取正在连接的客户端对象
                Socket s = ss.accept();
                //    3. 获取字节输入流  用来接收客户端发送的数据
                InputStream in = s.getInputStream();
                //    4. 创建文件字节输出流 绑定数据目的
                FileOutputStream fos = new FileOutputStream("D:\\2development\\abc\\mm.jpg");
                //    5. 循环读写
                byte[] bytes = new byte[1024];
                int len = 0;
                while((len = in.read(bytes)) != -1){
                    fos.write(bytes,0,len);
                }

                System.out.println("--------------向客户端返回数据--------------");

                //    6. 获取字节输出流对象
                OutputStream out = s.getOutputStream();
                //    7. 向客户端返回数据"上传成功"
                out.write("上传成功".getBytes());
                //    8. 关闭资源
                out.close();
                in.close();
                fos.close();
                s.close();
                ss.close();
            }
        }
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值