• 网络编程


    一、网络编程入门

          1.软件结构: 

    •  C/S结构: 全称Client/Server结构,是指客户端和服务器结构;
    •  B/S结构: 全称Browser/Server结构,是指浏览器和服务器结构;

          2.网络协议

    •  网络通信协议通过计算机网络可以使多台计算机实现连接,位于同一个网络中的计算机在进行连接和通信时需要遵守一定的规则;
    •   TCP/IP协议:传输控制协议/因特网互联协议( Transmission Control Protocol/Internet Protocol),是Internet最基本、最广泛的协议,并采用了4层的分层模型:

             

        链路层:链路层是用于定义物理传输通道,通常是对某些网络连接设备的驱动协议,例如针对光纤、网线提供的驱动。

        网络层:网络层是整个TCP/IP协议的核心,它主要用于将传输的数据进行分组,将分组数据发送到目标计算机或者网络。

        运输层:主要使网络程序进行通信,在进行网络通信时,可以采用TCP协议,也可以采用UDP协议。

        应用层:主要负责应用程序的协议,例如HTTP协议、FTP协议等。

           3.协议分类

               3.1.UDP:

                概念:用户数据报协议(User Datagram Protocol)。UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。

                 特点:由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议;

                注意:数据被限制在64kb以内,超出这个范围就不能发送了。

              3.2.TCP

                概念:传输控制协议 (Transmission Control Protocol)。TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。  

        在TCP连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手”。

    • 三次握手:TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠。

      • 第一次握手,客户端向服务器端发出连接请求,等待服务器确认。

      • 第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求。

      • 第三次握手,客户端再次向服务器端发送确认信息,确认连接

                  

              注: TCP协议可以保证传输数据的安全,例如下载文件、浏览网页等。

            4.网络编程的三要素

               1)协议;

               2)IP地址:指互联网协议地址(Internet Protocol Address),俗称IP;

                    分类:                         

    • IPv4:是一个32位的二进制数,通常被分为4个字节,表示成a.b.c.d 的形式,例如192.168.65.100 。其中a、b、c、d都是0~255之间的十进制整数,那么最多可以表示42亿个。

    • IPv6:由于互联网的蓬勃发展,IP地址的需求量愈来愈大,但是网络地址资源有限,使得IP的分配越发紧张。

      为了扩大地址空间,拟通过IPv6重新定义地址空间,采用128位地址长度,每16个字节一组,分成8组十六进制数,表示成ABCD:EF01:2345:6789:ABCD:EF01:2345:6789,号称可以为全世界的每一粒沙子编上一个网址,这样就解决了网络地址资源数量不够的问题。

               3)端口号

                     端口号:用两个字节表示的整数,它的取值范围是0~65535。其中,0~1023之间的端口号用于一些知名的网络服务和应用,普通的应用程序需要使用1024以上的端口号。如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败。

                      利用协议+IP地址+端口号 三元组合,就可以标识网络中的进程了,那么进程间的通信就可以利用这个标识与其它进程进行交互。

    二、TCP通信程序

              1.两端通信时步骤:

                  1)服务端程序(Server),需要事先启动,等待客户端(Client)的连接。

                  2)客户端主动连接服务器端,连接成功才能通信。服务端不可以主动连接客户端。             

            在Java中,提供了两个类用于实现TCP通信程序:

                 1)客户端:java.net.Socket 类表示。创建Socket对象,向服务端发出连接请求,服务端响应请求,两者建立连接开始通信。

                  2)服务端:java.net.ServerSocket 类表示。创建ServerSocket对象,相当于开启一个服务,并等待客户端的连接。

             2.Socket类

                 构造方法: 

           public Socket(String host, int port) :创建套接字对象并将其连接到指定主机上的指定端口号。如果指定的host是null ,则相当于指定地址为回送地址。

    Socket client = new Socket("127.0.0.1", 6666);

              成员方法:               

    • public InputStream getInputStream() : 返回此套接字的输入流。

      • 如果此Scoket具有相关联的通道,则生成的InputStream 的所有操作也关联该通道。

      • 关闭生成的InputStream也将关闭相关的Socket。

    • public OutputStream getOutputStream() : 返回此套接字的输出流。

      • 如果此Scoket具有相关联的通道,则生成的OutputStream 的所有操作也关联该通道。

      • 关闭生成的OutputStream也将关闭相关的Socket。

    • public void close() :关闭此套接字。

      • 一旦一个socket被关闭,它不可再使用。

      • 关闭此socket也将关闭相关的InputStream和OutputStream 。

    • public void shutdownOutput() : 禁用此套接字的输出流。

      • 任何先前写出的数据将被发送,随后终止输出流。

            3.ServerSocket类

              构造方法:

                 public ServerSocket(int port) :使用该构造方法在创建ServerSocket对象时,就可以将其绑定到一个指定的端口号上,参数port就是端口号。(该端口必须与Client中指定的端口号一致);   

    ServerSocket server = new ServerSocket(6666);

              成员方法:

             public Socket accept() :侦听并接受连接,返回一个新的Socket对象,用于和客户端实现通信。该方法会一直阻塞直到建立连接。

    综合练习:文件上传:

            服务器端:

              

    public class FileUpload_Server {
        public static void main(String[] args) throws IOException {
            System.out.println("服务器 启动.....  ");
            // 1. 创建服务端ServerSocket
            ServerSocket serverSocket = new ServerSocket(6666);
            // 2. 循环接收,建立连接
            while (true) {
                Socket accept = serverSocket.accept();
                  /*
                  3. socket对象交给子线程处理,进行读写操作
                   Runnable接口中,只有一个run方法,使用lambda表达式简化格式
                */
                new Thread(() -> {
                    try (
                        //3.1 获取输入流对象
                        BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());
                        //3.2 创建输出流对象, 保存到本地 .
                        FileOutputStream fis = new FileOutputStream(System.currentTimeMillis() + ".jpg");
                        BufferedOutputStream bos = new BufferedOutputStream(fis);
                    ) {
                        // 3.3 读写数据
                        byte[] b = new byte[1024 * 8];
                        int len;
                        while ((len = bis.read(b)) != -1) {
                            bos.write(b, 0, len);
                        }
    
                        // 4.=======信息回写===========================
                        System.out.println("back ........");
                        OutputStream out = accept.getOutputStream();
                        out.write("上传成功".getBytes());
                        out.close();
                        //================================
    
                        //5. 关闭 资源
                        bos.close();
                        bis.close();
                        accept.close();
                        System.out.println("文件上传已保存");
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }).start();
            }
        }
    }

    客户端:

          

    public class FileUpload_Client {
        public static void main(String[] args) throws IOException {
            // 1.创建流对象
            // 1.1 创建输入流,读取本地文件
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("test.jpg"));
            // 1.2 创建输出流,写到服务端
            Socket socket = new Socket("localhost", 6666);
            BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
    
            //2.写出数据.
            byte[] b  = new byte[1024 * 8 ];
            int len ;
            while (( len  = bis.read(b))!=-1) {
                bos.write(b, 0, len);
            }
              // 关闭输出流,通知服务端,写出数据完毕
            socket.shutdownOutput();
            System.out.println("文件发送完毕");
            // 3. =====解析回写============
            InputStream in = socket.getInputStream();
            byte[] back = new byte[20];
            in.read(back);
            System.out.println(new String(back));
            in.close();
            // ============================
    
            // 4.释放资源
            socket.close();
            bis.close();
        }
    }
  • 相关阅读:
    du 命令计算隐藏文件夹或文件
    QEMU中VIRTIO实现
    virtio_blk
    网络虚拟化Virtio-net
    virtio desc
    vhost dpdk 共享内存
    gvisor 信号处理
    Java idea 执行单个测试方法
    Java idea 创建User.xml,需要新增一个mybatis-mapper.xml模板
    Java idea 创建log4j.properties
  • 原文地址:https://www.cnblogs.com/cqyp/p/12425392.html
Copyright © 2020-2023  润新知