MENU

Java-61 网络编程

December 23, 2023 • Read: 68 • Java阅读设置

网络编程

简单地说,就是实现在网络中的数据传输,或者说,网络中的IO。

网络编程的介绍

1)网络编程的目的:
直接或间接地通过网络协议与其他计算机实现数据交换,进行通信。

2)网络编程中有两个主要的问题:

  • 如何准确地定位网络上的一台或多台主机、定位主机上的特定的应用;
  • 定位后如何可靠地进行数据传输。

3)网络编程中的两个主要的问题就对应网络通信中的2个要素:

  • IP和端口号

    • IP用来定位主机
    • 端口号用来定位具体的进程
  • 网络通信协议

    • TCP/IP参考模型:应用层、传输层、网络层、物理+数据链路层

网络通信要素一:IP和端口号

1 IP

1) IP是用于唯一标识Internet上的计算机(通信实体)。本地回路地址为:127.0.0.1,对应着localhost

2) InetAddress是Java中用来表示IP的类,即一个InetAddress对象对应一个IP或者说主机
2023-12-23T01:16:59.png

3) InetAddress的实例化,该类私有化了构造器,只能通过其方法来实例化,常用的两个方法为:

  • public static InetAddress getByName(String host) throws UnknownHostException: 该方法返回参数host对应的InetAddress对象,参数host既可以是IP地址,也可以是域名。
  • public static InetAddress getLocalHost() throws UnknownHostException: 该方法返回本地主机对应的InetAddress对象。

2023-12-23T01:20:33.png
2023-12-23T01:20:47.png

4)InetAddress对象的两个常用方法:

  • public String getHostAddress():该方法获取对应的IP地址;
  • public String getHostName():该方法获取对应的域名。

5)示例

  • 实例化InetAddress
    2023-12-23T01:31:13.png
  • InetAddress对象的两个常用方法:
    2023-12-23T01:33:19.png

2 端口号

1)端口号是用来标识正在计算机上运行的进程或者说程序。

  • 不同的进程有不同的端口号;
  • 端口号规定为一个16位的整数:0~65535;
  • 端口分类:

    • 公认端口:0~1023,被预先定义的服务通信占用。如HTTP占用端口80,FTP占用端口21,Telnet占用端口23。
    • 注册端口:1024~49151,分配给用户进程或应用程序。如Tomcat占用端口8080,MySQL占用端口3306,Oracle占用端口1521等。注意,这些并不是固定的,是默认端口,可以自己去指定端口。
    • 动态/私有端口:49152~65535。

2)端口号和IP地址的组合得到一个网络套接字:Socket。因此,Socket相当于就是用来确定网络中的一个节点,类似于IO中文件节点。

网络通信要素二:网络协议

2023-12-23T02:41:59.png
2023-12-23T02:42:16.png
2023-12-23T02:43:41.png

TCP网络编程

1 TCP网络编程说明

TCP网络编程涉及客户端和服务器端:

  • 客户端:

    • 自定义
    • 浏览器
  • 服务器端

    • 自定义
    • Tomcat服务器

TCP网络编程的一般流程:

  • 客户端

    • 通过实例化Socket创建要与服务器端进行通信的客户端socket;
    • 通过客户端socket的获取输入/输出流方法提供客户端到服务器端通信的输入/输出流;
    • 通过输入/输出流对应的读/写方法进行读/写;
    • 关闭相关资源。
  • 服务器端

    • 通过实例化ServerSocket创建服务器端socket;
    • 通过服务器端socket的accept方法得到服务器端接收到的客户端socket,注意这里的客户端socket是指服务器端接收到的socket,属于服务器socket的一部分,可以理解为服务器端专门为接收到的连接而创建的代表接收到的客户的socket,因此如果服务器端要从中获取数据,应该使该socket提供输入流而不是输出流;
    • 通过接收到的客户的socket提供对应的输入/输出流;
    • 通过输入/输出流对应的读/写方法进行读/写;
    • 关闭相关资源。

注意,在通信过程中,read方法是会一直阻塞在读取数据中的,直到确认另一方输出数据完成。因此,如果客户端只给服务器端发送一次数据就关闭资源,不会出现任何异常,但是如果客户端给服务器发送一次数据后还有后续通信,此时必须显式地在发送数据完成后面使用shutdown方法告诉服务器端发送数据完成,否则服务器端将一直阻塞在读取第一次传送来的数据的地方。

这里涉及到的主要的类为SocketServerSocket:

  • Socket是指java.net.Socket,该类实现客户端套接字(也称为“套接字”)。套接字是两台机器之间通信的端点。

    • 常用的对应实例化的构造器为:Socket(InetAddress address, int port),参数用来指定要通信的服务器端的IP和端口号。
      2023-12-23T03:27:00.png
    • 常用的对应的提供输入/输出流的方法为:

      • public InputStream getInputStream() throws IOException
      • public OutputStream getOutputStream() throws IOException
  • ServerSocket是指java.net.ServerSocket,该类实现服务器套接字。服务器套接字等待通过网络进入的请求。它根据该请求执行一些操作,然后可能将结果返回给请求者。

    • 常用的对应实例化的构造器为:public ServerSocket(int port) throws IOException,参数用来指定本服务器的端口号。
    • 常用的对应的为接收到的客户连接创建sokcet的方法为:

      • public Socket accept() throws IOException

TCP网络编程的注意点为,TCP网络编程中服务器端要先运行,这样客户端在创建对应Socket进行连接时才能连接成功,才能继续通信,否则连接失败,无法后续通信。因为TCP就是先建立连接,再进行通信。

2 示例1:客户端发送信息给服务端,服务端将数据显示在控制台上

解题思路:

  • 客户端

    • 通过实例化Socket创建要与服务器端进行通信的客户端socket;
    • 通过客户端socket的获取输出流方法提供客户端到服务器端通信的输出流;
    • 通过输出流对应的写方法进行写;
    • 关闭相关资源。
  • 服务器端

    • 通过实例化ServerSocket创建服务器端socket;
    • 通过服务器端socket的accept方法得到服务器端接收到的客户端socket;
    • 通过接收到的客户的socket提供对应的输入流;
    • 通过输入流对应的读方法进行读,将读取的数据打印到控制台;
    • 关闭相关资源。
  • client
    2023-12-23T03:48:51.png
  • server
    2023-12-23T03:49:08.png
  • 结果
    2023-12-23T03:49:28.png
    2023-12-23T03:49:39.png

3 示例2:客户端发送文件给服务端,服务端将文件保存在本地

  • 客户端

    • 通过实例化Socket创建要与服务器端进行通信的客户端socket;
    • 通过客户端socket的获取输出流方法提供客户端到服务器端通信的输出流;
    • 将要传输的文件数据通过对应文件的File的输入流读到当前客户端中;
    • 通过输出流对应的写方法将读来的文件数据进行写;
    • 关闭相关资源。
  • 服务器端

    • 通过实例化ServerSocket创建服务器端socket;
    • 通过服务器端socket的accept方法得到服务器端接收到的客户端socket;
    • 通过接收到的客户的socket提供对应的输入流;
    • 创建保存文件对应的File,并提供其输出流;
    • 通过输入流对应的读方法进行读,将读取的数据读到要保存的文件对应的输出流中;
    • 关闭相关资源。
  • client
    2023-12-23T04:10:32.png
  • server
    2023-12-23T04:10:45.png
  • 结果
    2023-12-23T04:10:57.png
    2023-12-23T04:11:06.png
    2023-12-23T04:11:18.png

4 示例3:从客户端发送文件给服务端,服务端保存到本地,并返回“发送成功”给客户端

  • 客户端

    • 通过实例化Socket创建要与服务器端进行通信的客户端socket;
    • 通过客户端socket的获取输出流方法提供客户端到服务器端通信的输出流;
    • 将要传输的文件数据通过对应文件的File的输入流读到当前客户端中;
    • 通过输出流对应的写方法将读来的文件数据进行写;
    • 显式地关闭输出流,以告知服务器端输出数据完成,否则服务器端将一直阻塞在读取数据中等待输出数据完成;
    • 通过客户端socket的获取输入流方法提供服务器端到客户端通信的输入流;
    • 通过输入流对应的读方法将服务器端传来的数据读入到控制台;
    • 关闭相关资源。
  • 服务器端

    • 通过实例化ServerSocket创建服务器端socket;
    • 通过服务器端socket的accept方法得到服务器端接收到的客户端socket;
    • 通过接收到的客户的socket提供对应的输入流;
    • 创建保存文件对应的File,并提供其输出流;
    • 通过输入流对应的读方法进行读,将读取的数据读到要保存的文件对应的输出流中;
    • 通过接收到的客户的socket提供对应的输出流;
    • 通过输出流对应的写方法进行写;
    • 关闭相关资源。
  • client
    2023-12-23T04:35:53.png
  • server
    2023-12-23T04:36:08.png
  • 结果
    2023-12-23T04:36:20.png
    2023-12-23T04:36:29.png

UDP网络编程

UDP网络编程涉及发送端和接收端。

DatagramSocketDatagramPacket实现了基于UDP协议网络程序。

UDP数据报通过数据报套接字DatagramSocket发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。也就是说,UDP网络编程并不要求先启动接收端再启动发送端。

DatagramPacket对象封装了UDP的数据报,在数据报中包含了发送端的IP和端口号以及接收端的IP地址和端口号。

UDP协议中每个数据报都给出了完整的地址信息,因此无需建立发送方和接收方的连接。

UDP网络编程的一般流程:

  • 发送端

    • 通过实例化DatagramSocket创建发送端;
    • 准备好数据,通过实例化DatagramPacket提供发送的数据;
    • 以发送的数据为参数,使用发送端的DatagramSocket的发送方法将数据发送出去;
    • 关闭相关资源。
  • 接收端

    • 通过实例化DatagramSocket创建接收端;
    • 通过实例化DatagramPacket,为接收到的数据创建对应的DatagramPacket来装;
    • 以创建的DatagramPacket为参数,使用接收端DatagramSocket的接收方法将数据接收到创建的DatagramPacket中;
    • 使用DatagramPacket的获取数据方法来得到接收到的数据对应的字节数组;
    • 关闭相关资源。

这里主要涉及到的类为DatagramSocketDatagramPacket

  • DatagramSocket是指java.net.DatagramSocket,该类表示用于发送和接收数据报的套接字。

    • 常用构造器为空参构造器和以端口号为参数的构造器,后者用于创建接收端
      2023-12-23T05:58:24.png
    • 常用发送、接收方法为:

      • public void send(DatagramPacket p) throws IOException
      • public void receive(DatagramPacket p) throws IOException
  • DatagramPacket是指java.net.DatagramPacket,该类表示一个数据报。

    • 常用构造器为public DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)
      2023-12-23T06:00:19.png
    • 常用读取数据方法为:

      • public byte[] getData():得到接收数据的字节数组;
      • public int getLength():得到实际接收到的数据的长度。

UDP网络编程示例:

  • sender
    2023-12-23T06:22:14.png
  • recieve
    2023-12-23T06:22:31.png
  • 结果
    2023-12-23T06:22:45.png
    2023-12-23T06:22:55.png

URL网络编程

URL

2023-12-23T06:37:07.png

Java中URL类代表URL,其是指java.net.URL

URL的格式为:协议://主机名:端口号/资源地址?参数列表,例如http://localhost:8080/examples/beauty.jpg?username=Tom

URL常用的构造器为:public URL(String spec) throws MalformedURLException
2023-12-23T06:38:25.png

URL对象的常用方法为:

  • public String getProtocol():获取对应URL的协议;
  • public String getHost():获取对应URL的主机名;
  • public int getPort():获取对应URL的端口号;
  • public String getPath():获取对应URL的文件路径;
  • public String getFile():获取对应URL的文件名;
  • public String getQuery():获取对应URL的参数列表。

示例:
2023-12-23T06:48:31.png

URL网络编程的一般流程:

  • 通过实例化URL来创建对应的要访问的URL资源;
  • 通过使用URL对应的public URLConnection openConnection() throws IOException方法创建对该URL资源的连接对象,注意该连接对象可以理解为用来接收连接到的对应的URL的对象;
  • 使用连接对象对应的connect()方法进行与连接对象真正的连接;
  • 连接后,使用连接对象的getInputStream()提供从接收到的连接对象获取数据的输入流;
  • 使用流对应的读方法进行数据传输;
  • 关闭资源,注意这里要对连接进行关闭,即对连接对象使用disconnect()方法。

2023-12-23T06:56:21.png
2023-12-23T06:57:23.png
2023-12-23T06:57:38.png