【学习笔记】Java笔记9:网络编程

68 阅读4分钟

1. 相关概念

1.1 IP

  • 唯一标识Internet上的计算机

  • 分类方式1:IPV4和IPV6

    • IPV4:4个字节组成,4个0~255,中间用小数点隔开,如192.168.0.1
    • IPV6:128位(16个字节)组成,8组无符号整数,中间用冒号隔开,如3ffe:3201:1401:1280:c8ff:fe4d:db39:1984
  • 分类方式2:公网地址(万维网)和私网地址(局域网),192.168.开头的就是私有地址

  • 在Java中对应的类是InetAddress

  • 本地地址:127.0.0.1对应域名是localhost

1.2 端口

  • 标识计算机运行的进程

  • 不同的进程有不同的端口号

  • 端口号是一个16位的整数,范围0~65535

  • 分类如下

    • 公认端口:0~1023,被预先定义的服务通信占用。如HTTP占用80,FTP占用21

    • 注册端口:1024~49151,分配给用户进程或应用程序。如Tomcat占用8080,MySQL占用3306,Oracle占用1521

    • 动态/私有端口:49152~65535

  • 端口号与IP地址组合成一个网络套接字:Socket

1.3 网络协议

  网络协议即网络通信中的一些约定。传输层的两个重要协议:TCP和UDP

1.3.1 TCP

  • 使用TCP协议前,需建立TCP连接,形成数据传输通道
  • 传输前,要进行"三次握手";传输完毕后,要进行"四次挥手"
  • TCP的两个应用进程:客户端、服务端
  • 连接中可以进行大量数据的传输
  • 传输完成需要释放连接,效率低

1.3.2 UDP

  • 不建立连接
  • 每个数据报限制在64K内
  • 只管发送,不管对方是否接收到
  • 可以广播发送
  • 发送结束不释放资源,速度快

2. TCP和UDP编程

2.1 TCP

2.1.1 例题1

  需求:客户端向服务端发送数据,服务端打印到控制台上

public class TCPTest {
    @Test
    public void client() {
        Socket socket = null;
        OutputStream os = null;
        try {
            InetAddress inet = InetAddress.getByName("127.0.0.1");
            // 创建Socket对象,指名服务器的ip和端口
            socket = new Socket(inet, 8888);
            // 获取输出流,用于向服务器输出数据
            os = socket.getOutputStream();
            os.write("我是客户端".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != os) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != socket) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Test
    public void server() {
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;
        try {
            // 创建服务器的ServerSocket对象,指名自身的端口
            serverSocket = new ServerSocket(8888);
            // 调用accept()方法接收客户端的socket
            socket = serverSocket.accept();
            // 获取socket的输入流
            is = socket.getInputStream();

            baos = new ByteArrayOutputStream();
            byte[] buff = new byte[20];
            int len;
            while (-1 != (len = is.read(buff))) {
                baos.write(buff, 0, len);
            }
            System.out.println(baos.toString());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != baos) {
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != socket) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != serverSocket) {
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

2.1.2 例题2

  需求:客户端向服务端发送文件,服务端把文件保存在硬盘上

public class TCPTest2 {
   @Test
   public void client() throws IOException {
       Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 8888);
       OutputStream os = socket.getOutputStream();
       FileInputStream fis = new FileInputStream("E:\\JavaTest\\client\\01.jpg");

       byte[] buff = new byte[1024];
       int len;
       while (-1 != (len = fis.read(buff))) {
           os.write(buff, 0 , len);
       }
       // 这里偷懒直接把异常抛出,正常开发应该用try-catch-finally
       fis.close();
       os.close();
       socket.close();
   }

   @Test
   public void server() throws IOException {
       ServerSocket serverSocket = new ServerSocket(8888);

       Socket socket = serverSocket.accept();
       InputStream is = socket.getInputStream();

       FileOutputStream fos = new FileOutputStream("E:\\JavaTest\\server\\01.jpg");
       byte[] buff = new byte[1024];
       int len;
       while (-1 != (len = is.read(buff))) {
           fos.write(buff, 0, len);
       }

       fos.close();
       is.close();
       socket.close();
       serverSocket.close();
   }
}

2.1.3 例题3

  需求:在例题2的基础上,服务端反馈"接收完成"给客户端

public class TCPTest3 {
    @Test
    public void client() throws IOException {
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 8888);
        OutputStream os = socket.getOutputStream();
        FileInputStream fis = new FileInputStream("E:\\JavaTest\\client\\01.jpg");

        byte[] buff = new byte[1024];
        int len;
        while (-1 != (len = fis.read(buff))) {
            os.write(buff, 0 , len);
        }

        // 不调用该方法会导致阻塞
        socket.shutdownOutput();

        // 接收服务端的数据
        InputStream is = socket.getInputStream();
        InputStreamReader isr = new InputStreamReader(is);
        char[] buff2 = new char[10];
        StringBuilder sb = new StringBuilder(100);
        int len2;
        while (-1 != (len2 = isr.read(buff2))) {
            sb.append(buff2, 0, len2);
        }
        System.out.println(sb.toString());

        isr.close();
        is.close();
        fis.close();
        os.close();
        socket.close();
    }

    @Test
    public void server() throws IOException {
        ServerSocket serverSocket = new ServerSocket(8888);

        Socket socket = serverSocket.accept();
        InputStream is = socket.getInputStream();

        FileOutputStream fos = new FileOutputStream("E:\\JavaTest\\server\\01.jpg");
        byte[] buff = new byte[1024];
        int len;
        while (-1 != (len = is.read(buff))) {
            fos.write(buff, 0, len);
        }

        OutputStream os = socket.getOutputStream();
        os.write("接收完成".getBytes());

        os.close();
        fos.close();
        is.close();
        socket.close();
        serverSocket.close();
    }
}

2.2 UDP

public class UDPTest {
    @Test
    public void sender() throws Exception {
        DatagramSocket socket = new DatagramSocket();

        byte[] data = "UDP传输".getBytes();

        InetAddress inet = InetAddress.getByName("127.0.0.1");
        DatagramPacket packet = new DatagramPacket(data, 0, data.length, inet, 8888);

        socket.send(packet);

        socket.close();
    }

    @Test
    public void receiver() throws Exception {
        DatagramSocket socket = new DatagramSocket(8888);

        byte[] buff = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buff, 0, buff.length);
        socket.receive(packet);

        System.out.println(new String(packet.getData(), 0, packet.getLength()));
    }
}

3. 相关链接