1. Overview of network programming
- Java is a language on the Internet. It provides support for network applications at the language level. Programmers can easily develop common network applications.
- The network class library provided by java can realize painless network connection. The underlying details of networking are hidden in the Java Native installation system and controlled by the JVM. And Java implements a cross platform network library. Programmers face a unified network programming environment.
- The purpose of network programming is to realize data exchange and communication with other computers directly or indirectly through network protocol.
- There are two main problems in network programming:
① How to accurately locate one or more hosts on the network; Locate a specific application on the host
② How to transfer data reliably and efficiently after finding the host
Expand small knowledge
What is computer network?
It interconnects computers distributed in different geographical regions and special external equipment with communication lines to form a large-scale and powerful network system, so that many computers can easily transfer information and share hardware, software, data information and other resources.
2. Overview of network communication elements
Elements of network communication (solving the above two problems):
- Address of communication parties (IP + port number)
- Certain rules (network communication protocol) two sets of reference models:
① OSI reference model: the model is too idealized to be widely popularized on the Internet
② TCP/IP reference model (or TCP/IP Protocol): a de facto international standard.
2.1 IP and port numbers
2.1.1 IP address
IP address is the unique identification (communication entity) of the computer on the Internet. InetAddress class represents IP in Java class
1, IP address classification
- IPV4 and IPV6
IPV4: 4 bytes, 4 0-255. About 4.2 billion and 3 billion are in North America and 400 million in Asia. It was exhausted in early 2011. Expressed in dotted decimal system, such as 192.168.0.1
IPV6: 128 bits (16 bytes), written as 8 unsigned integers. Each integer is represented by four hexadecimal bits, separated by colons (:), such as 3ffe:3201:1401:1280:c8ff:fe4d:db39:1984 - Public address (for World Wide Web use) and private address (for LAN use). 192.168. The private address at the beginning is 192.168.0.0 – 192.168.255.255, which is specially used within the organization.
2, Local loopback address
Local loop address (hostAddress): 127.0.0.1
Corresponding host name (hostName): localhost
3, Hosts on the Internet can represent addresses in two ways
- Domain name (hostName): www.atguigu.com com
- IP address (hostAddress): 202.108.35.210
Characteristics of IP address and domain name
IP address: hard to remember
Domain name: easy to remember. When a host's domain name is entered when connecting to the network, the domain name server (DNS) is responsible for converting the domain name into an IP address, so as to establish a connection with the host------- Domain name resolution
Resolution process:
- Find the local hosts file first. Check whether there is a record of the domain name address. If yes, access it directly
- If not, find the host address through the DNS server
The hosts file is commonly used in future development. You can understand it first
4, InetAddress class
It mainly represents the IP address, which is divided into two subclasses: Inet4Address and Inet6Address.
The InetAddress class object contains the domain name and IP address of an Internet host address: www.atguigu.com COM and 202.108.35.210.
How to instantiate InetAddress: two methods: getByName(String host) and getLocalHost()
Two common methods: getHostName() / getHostAddress()
Use example
import java.net.InetAddress; import java.net.UnknownHostException; public class InetAddressTest { public static void main(String[] args) { try { InetAddress inet1 = InetAddress.getByName("192.168.10.14"); // /192.168.10.14 System.out.println(inet1); InetAddress inet2 = InetAddress.getByName("www.atguigu.com"); System.out.println(inet2); // www.atguigu.com/60.217.246.27 InetAddress inet3 = InetAddress.getByName("127.0.0.1"); System.out.println(inet3); // /127.0.0.1 //Get local ip InetAddress inet4 = InetAddress.getLocalHost(); System.out.println(inet4); //getHostName() get domain name System.out.println(inet2.getHostName()); // www.atguigu.com //getHostAddress() get IP address System.out.println(inet2.getHostAddress()); // 60.217.246.27 } catch (UnknownHostException e) { e.printStackTrace(); } } }
2.1.2 port number
The port number identifies the process (program) running on the computer
- Requirement: different processes have different port numbers
- Range: specified as a 16 bit integer 0 ~ 65535.
Port classification:
- Recognized port: 0 ~ 1023. Occupied by predefined service communication (e.g. HTTP occupies port 80, FTP occupies port 21, Telnet occupies port 23)
- Registration port: 1024 ~ 49151. Assigned to a user process or application. (for example, Tomcat occupies port 8080, MySQL occupies port 3306, Oracle occupies port 1521, etc.).
- Dynamic / private ports: 49152 ~ 65535.
The combination of port number and IP address yields a network Socket: Socket.
2.2 network communication protocol
There must be some conventions to realize communication in computer network, that is, communication protocol, and formulate standards for rate, transmission code, code structure, transmission control steps, error control, etc.
Computer network communication involves many contents, such as specifying source address and target address, encryption and decryption, compression and decompression, error control, flow control and routing control. How to realize such a complex network protocol?
When making an agreement, break down the complex components into some simple components, and then combine them. The most commonly used composite method is the hierarchical method, that is, the same layer can communicate, the upper layer can call the next layer, and there is no relationship with the next layer. Each layer does not affect each other, which is conducive to the development and expansion of the system.
Comparison of TCP and UDP network communication protocols
There are two very important protocols in the transport layer protocol: transmission control protocol (TCP) and user datagram protocol (UDP).
TCP/IP is named after its two main protocols: transmission control protocol (TCP) and network interconnection protocol (IP). It is actually a group of protocols, including multiple protocols with different functions and related to each other.
- IP(Internet Protocol) protocol is the main protocol of network layer, which supports data communication between networks.
- From a more practical point of view, TCP/IP protocol model forms an efficient four layer architecture, namely physical link layer, IP layer, transport layer and application layer.
1, TCP protocol:
Before using TCP protocol, a TCP connection must be established to form a data transmission channel
Before transmission, the "triple handshake" mode is adopted for point-to-point communication, which is reliable
Two application processes communicating with TCP protocol: client and server.
Large amount of data can be transmitted during connection after transmission, the established connection needs to be released, which is inefficient
2, UDP protocol:
Encapsulate the data, source and destination into packets without establishing a connection
The size of each datagram is limited to 64K
Whether the sending party is ready or not, the receiving party does not confirm the receipt, so it is unreliable
Can broadcast and send
At the end of sending data, there is no need to release resources, low overhead and high speed
Knowledge development: three handshakes and four waves
1. Three handshakes
① Description: first, the Client sends a connection request message, and the Server replies to the ACK message after accepting the connection, and allocates resources for this connection. After receiving the ACK message, the Client also sends the ACK message to the Server and allocates resources, so that the TCP connection is established.
② Illustration:
Initially, the TCP processes at both ends are CLOSED. A (client) actively opens the connection, while B (server) passively opens the connection. (a, B CLOSED - B LISTEN - a sync sent status SYN-SENT - B sync received status SYN-RCVD - A, B connection ESTABLISHED status ESTABLISHED)
③ Detailed explanation:
Let's start with a few concepts:
SYN: synchronous bit (used to establish connection)
ACK: acknowledgement confirmation bit (1 indicates connection confirmation)
ACK: ack number
seq: Sequence number of the packet
TCB: Transmission Control Block, which stores important information in each connection.
1. The TCP server process of B first creates the transmission control block TCB and is ready to accept the connection request of the client process. The server process is then in the LISTEN state, waiting for the client's connection request. If so, respond.
2. First handshake: the TCP client process of A first creates the transmission control block TCB, and then sends A connection request message segment to B, (the synchronization bit of the header SYN=1, the initial sequence number seq=x), (the message segment of SYN=1 cannot carry data) but consumes A sequence number. At this time, the TCP client process enters the SYN-SENT state.
3. Second handshake: if B agrees to establish a connection after receiving the connection request message segment, it will send a confirmation to A. in the confirmation message segment (SYN=1, ACK=1, ack=x+1, initial sequence number seq=y), test the TCP server process to enter the SYN-RCVD (synchronous receipt) state;
4. The third Handshake: after receiving the confirmation from B, the TCP client process shall give B A confirmation message segment (ACK=1, confirmation number ack=y+1, sequence number seq=x+1) (the initial sequence number is seq=x, so the second message segment sent should be + 1). The ACK message segment can carry data, and if it does not carry data, it does not consume sequence number. The TCP connection has been ESTABLISHED, and A enters ESTABLISHED.
5. When B receives the confirmation from A, it also enters the ESTABLISHED state.
④ Summary:
First handshake: at first, both ends are CLOSED. The Client sets the flag SYN to 1, randomly generates a value seq=x, and sends the packet to the Server. The Client enters the SYN-SENT state and waits for the Server to confirm;
The second handshake: after the Server receives the data packet, the flag bit SYN=1 knows that the Client requests to establish a connection. The Server sets the flag bits SYN and ack to 1, ack=x+1, randomly generates a value seq=y, and sends the data packet to the Client to confirm the connection request. The Server enters the SYN-RCVD state. At this time, the operating system allocates TCP cache and variables for the TCP connection;
The third Handshake: after receiving the confirmation, the Client checks whether the ACK is x+1 and the ACK is 1. If it is correct, set the flag bit ack to 1 and ack=y+1. At this time, the operating system allocates TCP cache and variables for the TCP connection and sends the data packet to the Server. The Server checks whether the ACK is y+1 and ACK is 1. If it is correct, the connection is ESTABLISHED successfully, The Client and Server enter the ESTABLISHED state, complete the handshake three times, and then the Client and Server can start transmitting data.
Extended question 1: why should we shake hands three times and not twice?
Answer:
1. Prevent initialization of repeated historical connections
Prevent the failed connection request message from being suddenly transmitted to the server, resulting in an error. Suppose such A scenario: A sends A connection request message, which is delayed for A long time due to network problems. It does not arrive at B until the second connection communication releases the connection. This is an invalid connection request message. At this time, B thinks it is A new connection request sent by A, so it sends A confirmation character. If there is no three handshakes, the connection is established, but A does not send A connection request, Therefore, B will always wait for A to send the confirmation character. In this way, B waits for A long time and wastes B's resources in vain.
2. Reliable synchronization of serial number: (reliable transmission of TCP)
If it is two handshakes, the server cannot determine whether the client has received the initial serial number sent by itself. If the second handshake message is lost, the client cannot know the initial serial number of the server, and the reliability of TCP is impossible.
3. Confirm the sending and receiving capacity of both parties
The first handshake: the server comes to the conclusion that the client sends normally and the server receives normally.
The second handshake: the client gets the conclusion that the server receives and sends normally, and the client receives and sends normally. However, at this time, the server cannot determine whether the receiving capacity of the client is normal.
The third Handshake: the server comes to the conclusion that the client receives and sends normally, and the server receives and sends normally.
Extension question 2: why is the Server vulnerable to SYN attacks?
A: the Server-side resources are allocated during the second handshake, while the Client-side resources are allocated during the third handshake, so the Server is vulnerable to SYN flooding attack. Syn attack is that the Client forges a large number of nonexistent IP addresses in a short time, and continuously sends syn packets to the Server. The Server replies to the confirmation packet and waits for the Client's confirmation. Because the source address does not exist, the Server needs to resend until it times out. These forged syn packets will occupy the unconnected queue for a long time, resulting in the normal syn requests being discarded because the queue is full, resulting in network congestion and even system paralysis.
Measures to prevent SYN attack: reduce the waiting time of the host, so that the host can release the occupation of half connection as soon as possible. If it is repeated by an IP for a short time, SYN will discard subsequent requests.
2. Four waves
① Brief description
- The Client side initiates a connection interruption request (sends FIN message).
It means: I have no data to send to you (Server side) on the Client side, but if you (Server side) still have data to send, you don't have to close the Socket in a hurry and you can continue to send data. - After receiving the FIN message, the Server sends an ACK back to the Client.
I have received your request (Client side), but I (Server side) are not ready. Please continue to wait for my message. - Client enters FIN_WAIT status, continue to wait for FIN message on Server side.
- The Server side confirms that the data has been sent, and sends FIN message to the Client side.
Tell the Client that my data has been sent and I am ready to close the connection. - After receiving the FIN message, the Client sends an ACK to enter TIME_WAIT status.
It means that the Client knows that the connection can be closed after receiving the FIN message, but he still doesn't believe in the network. He's afraid that the Server doesn't know to close, so he enters time after sending an ACK_ Wait status. If the Server does not receive an ACK, it can be retransmitted. - Close the connection after the Server receives the ACK.
- The Client side still does not receive a reply after waiting for 2MSL, which proves that the Server side has been closed normally and the Client side has also closed the connection.
- TCP connection closed.
② Illustration
After the data transmission, both sides of the communication can release the connection, and both A and B are in the ESTABLISHED state. (A, B connection establishment status ESTABLISHED - A terminate wait 1 status FIN-WAIT-1 - B close wait - A terminate wait 2 status FIN-WAIT-2 - B last confirm status LAST-ACK - A time wait status TIME-WAIT - B, A close status)
③ Explain in detail
FIN: close connection
1. Waving for the first time: the application process of A first sends A connection release message segment (FIN=1, sequence number seq=u) to its TCP, stops sending data again, actively closes the TCP connection, enters the FIN-WAIT-1 state, and waits for the confirmation of B.
2. After the second wave, B sends A confirmation message segment after receiving the connection release message segment (ACK=1, ack=u+1, seq=v). B enters the CLOSE-WAIT state. At this time, TCP is in the semi closed state, and the connection from A to B is released.
3. A fter receiving the confirmation from B, a enters the FIN-WAIT-2 state and waits for the connection release message segment sent by B.
4. For the third wave, B has no data to send to A, B sends the connection release message segment (FIN=1, ACK=1, seq=w, ack=u+1), B enters the LAST-ACK state and waits for A's confirmation.
5. After waving for the fourth time, A receives the connection release message segment of B, sends A confirmation message segment (ACK=1, seq=u+1, ack=w+1), and A enters the TIME-WAIT state. At this time, TCP is not released, and A needs to wait for 2MSL set by the timer before entering the CLOSED state.
Extended question 1: why does A have to wait for 2MSL in TIME-WAIT state?
MSL Maximum Segment Lifetime, MSL=2
Answer:
- Ensure that the last ACK message segment sent by A can reach B. This ACK message segment may be lost, so that B in the LAST-ACK state cannot receive the confirmation of the sent FIN+ACK message segment, and retransmit the FIN+ACK message segment in case of B-ultrasound.
A can receive the retransmitted FIN+ACK message segment within 2MSL time, then a retransmits a confirmation, restarts the 2MSL timer, and finally both a and B enter the CLOSED state.
If A does not wait for A period of time in the TIME-WAIT state, but releases the connection immediately after sending the ACK message segment, it cannot receive the FIN+ACK message segment retransmitted by B, so it will not send the confirmation message segment again, and B cannot normally enter the CLOSED state. - Prevent "invalid connection request message segment" from appearing in this connection. A after sending the last ACK message segment and passing through 2MSL, all message segments generated during the duration of this connection can disappear from the network, so that this old connection request message segment will not appear in the next new connection.
Extended question 2: why do you shake hands three times when connecting and four times when closing?
A: because when the Server receives the SYN connection request message from the Client, it can directly send the SYN+ACK message. The ACK message is used for response and the SYN message is used for synchronization. However, when closing the connection, when the Server receives the FIN message, it is likely that the SOCKET will not be closed immediately, so it can only reply to an ACK message and tell the Client, "I received the FIN message you sent". I can only send FIN messages when all messages on my Server are sent, so I can't send them together. Therefore, four steps are required.
3. TCP network programming
import org.junit.Test; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; /** * Network programming for TCP * Example 1: the client sends information to the server, and the server displays the data on the console */ public class TCPTest { //client @Test public void client() { Socket socket = null; OutputStream os = null; try { //1. Create a Socket object to indicate the ip and port number of the server InetAddress inet = InetAddress.getByName("192.168.14.100"); socket = new Socket(inet,8899); //2. Obtain an output stream for outputting data os = socket.getOutputStream(); //3. Write data os.write("Hello, this is the client HH".getBytes()); } catch (IOException e) { e.printStackTrace(); } finally { //4. Closure of resources if(os != null){ try { os.close(); } catch (IOException e) { e.printStackTrace(); } } if(socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } //Server @Test public void server() { ServerSocket ss = null; Socket socket = null; InputStream is = null; ByteArrayOutputStream baos = null; try { //1. Create a ServerSocket on the server side and indicate its own port number ss = new ServerSocket(8899); //2. Call accept() to receive the socket from the client socket = ss.accept(); //3. Get input stream is = socket.getInputStream(); //It is not recommended to write like this. There may be garbled code // byte[] buffer = new byte[1024]; // int len; // while((len = is.read(buffer)) != -1){ // String str = new String(buffer,0,len); // System.out.print(str); // } //4. Read the data in the input stream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[5]; int len; while((len = is.read(buffer)) != -1){ baos.write(buffer,0,len); } System.out.println(baos.toString()); System.out.println("Received from:" + socket.getInetAddress().getHostAddress() + "Data"); } catch (IOException e) { e.printStackTrace(); } finally { if(baos != null){ //5. Close resources try { baos.close(); } catch (IOException e) { e.printStackTrace(); } } if(is != null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if(socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } if(ss != null){ try { ss.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
Exercise 1: the client sends the file to the server, and the server saves the file locally.
import org.junit.Test; import java.io.*; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; public class TCPTest2 { /** * The exceptions involved here should be handled with try catch finally * @throws IOException */ @Test public void test() throws IOException { Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9090); OutputStream os = socket.getOutputStream(); FileInputStream fis = new FileInputStream(new File("164.jpg")); byte[] buffer = new byte[1024]; int len; while((len = fis.read(buffer)) != -1){ os.write(buffer,0,len); } fis.close(); os.close(); socket.close(); } /** * The exceptions involved here should be handled with try catch finally * @throws IOException */ @Test public void test2() throws IOException { ServerSocket ss = new ServerSocket(9090); Socket socket = ss.accept(); InputStream is = socket.getInputStream(); FileOutputStream fos = new FileOutputStream(new File("1641.jpg")); byte[] buffer = new byte[1024]; int len; while((len = is.read(buffer)) != -1){ fos.write(buffer,0,len); } fos.close(); is.close(); socket.close(); ss.close(); } }
Exercise 2: send files from the client to the server, and the server saves them locally. Return "send successfully" to the client and close the corresponding connection.
import org.junit.Test; import java.io.*; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; public class TCPTest3 { /** * The exceptions involved here should be handled with try catch finally * @throws IOException */ @Test public void test() throws IOException { Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9090); OutputStream os = socket.getOutputStream(); FileInputStream fis = new FileInputStream(new File("164.jpg")); byte[] buffer = new byte[1024]; int len; while((len = fis.read(buffer)) != -1){ os.write(buffer,0,len); } //Turn off data output socket.shutdownOutput(); //5. Receive data from the server and display it on the console InputStream is = socket.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] bufferr = new byte[20]; int len1; while((len1 = is.read(buffer)) != -1){ baos.write(buffer,0,len1); } System.out.println(baos.toString()); fis.close(); os.close(); socket.close(); baos.close(); } /** * The exceptions involved here should be handled with try catch finally * @throws IOException */ @Test public void test2() throws IOException { ServerSocket ss = new ServerSocket(9090); Socket socket = ss.accept(); InputStream is = socket.getInputStream(); FileOutputStream fos = new FileOutputStream(new File("1642.jpg")); byte[] buffer = new byte[1024]; int len; while((len = is.read(buffer)) != -1){ fos.write(buffer,0,len); } System.out.println("Picture transfer complete"); //6. The server gives feedback to the client OutputStream os = socket.getOutputStream(); os.write("Hello, I have received the photos. The scenery is good!".getBytes()); fos.close(); is.close(); socket.close(); ss.close(); os.close(); } }
4. UDP network programming
Datagram socket class and datagram packet class implement network program based on UDP protocol.
UDP datagrams are sent and received through datagram socket. The system does not guarantee that UDP datagrams can be safely sent to the destination, nor can it determine when they can arrive.
The datagram packet object encapsulates UDP datagrams, which contain the IP address and port number of the sender and the IP address and port number of the receiver.
Each datagram in UDP protocol gives complete address information, so there is no need to establish a connection between the sender and the receiver. It's like sending an express package.
technological process:
- Datagram socket and datagram packet
- Establish sender and receiver
- Create packet
- Call Socket sending and receiving methods
- Close Socket
Example
import org.junit.Test; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; /** * UDPd Network programming of protocol */ public class UDPTest { //Sender @Test public void sender() throws IOException { DatagramSocket socket = new DatagramSocket(); String str = "I am UDP Sender"; byte[] data = str.getBytes(); InetAddress inet = InetAddress.getLocalHost(); DatagramPacket packet = new DatagramPacket(data,0,data.length,inet,9090); socket.send(packet); socket.close(); } //receiving end @Test public void receiver() throws IOException { DatagramSocket socket = new DatagramSocket(9090); byte[] buffer = new byte[100]; DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length); socket.receive(packet); System.out.println(new String(packet.getData(),0,packet.getLength())); socket.close(); } }
5. URL programming
URL: uniform resource locator, corresponding to a resource address on the Internet
Format:
http://127.0.0.1:8080/work/164.jpg?username=zhangsan Protocol host name Port number resource address parameter list
import java.net.MalformedURLException; import java.net.URL; /** * URL Network programming * 1.URL:The uniform resource locator corresponds to a resource address on the Internet * 2.Format: * http://127.0.0.1:8080/work/164.jpg?username=subei * Protocol hostname port number resource address parameter list */ public class URLTest { public static void main(String[] args) { try { URL url = new URL("http://127.0.0.1:8080/work/164.jpg?username=zhangsan"); // public String getProtocol() gets the protocol name of the URL System.out.println(url.getProtocol()); // http // public String getHost() gets the host name of the URL System.out.println(url.getHost()); // 127.0.0.1 // public String getPort() gets the port number of the URL System.out.println(url.getPort()); // 8080 // public String getPath() gets the file path of the URL System.out.println(url.getPath()); // /work/164.jpg // public String getFile() gets the file name of the URL System.out.println(url.getFile()); // /work/164.jpg?username=zhangsan // public String getQuery() gets the query name of the URL System.out.println(url.getQuery()); // username=zhangsan } catch (MalformedURLException e) { e.printStackTrace(); } } }
5.1 URL network programming for Tomcat server data download
import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; public class URLTest1 { public static void main(String[] args) { HttpURLConnection urlConnection = null; InputStream is = null; FileOutputStream fos = null; try { URL url = new URL("http://127.0.0.1:8080/work/164.jpg"); // open a connection urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.connect(); // Get file input stream is = urlConnection.getInputStream(); // Specifies the output location of the file fos = new FileOutputStream("day10\\1643.jpg"); byte[] buffer = new byte[1024]; int len; while((len = is.read(buffer)) != -1){ fos.write(buffer,0,len); } System.out.println("Download complete"); } catch (IOException e) { e.printStackTrace(); } finally { //close resource if(is != null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if(fos != null){ try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } if(urlConnection != null){ urlConnection.disconnect(); } } } }
6. Difference between URI, URL and URN
URI is a uniform resource identifier, which is used to uniquely identify a resource.
URL is a uniform resource locator, a uniform resource locator. It is a specific URI, that is, the URL can be used to identify a resource, and also indicates how to locate the resource.
URN, uniform resource name, uniform resource name, identifies resources by name, such as mailto:java-net@java.sun.com .
In other words, URI is an abstract and high-level concept to define unified resource identification, while URL and URN are specific ways of resource identification. Both URL and URN are URIs.
In Java URIs, a URI instance can represent absolute or relative, as long as it conforms to the syntax rules of URIs. The URL class not only conforms to the semantics, but also contains the information to locate the resource, so it cannot be relative.
Last | General catalogue | Next |
---|---|---|
15, IO stream | Java basic directory | Unfinished to be continued |