Network applications are divided into two parts: client and server, and the Socket class is a Java class responsible for handling client communication. Through this class, you can connect to a server with a specified IP or domain name, and you can send and receive data with each other with the server. The use of Socket class will be discussed in detail in this article and several articles later, including the Socket class basics, various connection methods, get and set methods, timeouts during connection, and closing network connections, etc.
In this article, we will discuss the basic steps and methods of using the Socket class. Generally, network client programs must perform the following three steps when connecting to service programs.
1. Connect to the server
The client can connect to the server in two ways, one is to connect to the server through IP, and the other is to connect to the server through domain name.
In fact, these two methods are essentially one way. At the underlying client, they all connect to the server through IP, but there are certain differences between the two methods. If the server program is connected through IP, the client only simply connects according to IP. If the server is connected through domain name, the client must resolve the domain name into IP through DNS, and then connect according to this IP.
In many programming languages or development tools (such as C/C++, Delphi) when connecting to the server using domain name, you must first resolve the domain name to IP, and then connect through IP. In Java, the domain name resolution function has been included in the Socket class. Therefore, we only need to use the domain name like using IP.
The most common method of connecting to server programs through the Socket class is to pass the IP or domain name and port number as parameters into the Socket class through the Socket class constructor. There are many overloaded forms of the constructor of the Socket class. In this section, only one of the most commonly used forms is discussed: public Socket (String host, int port). From the definition of this constructor, you only need to pass the IP or domain name and port number directly into the constructor. The following code is an example program that connects to server programs:
package mysocket; import java.net.*; public class MyConnection{ public static void main(String[] args) { try { if (args.length > 0) { Socket socket = new Socket(args[0], 80); System.out.println(args[0] + "Connected successfully!"); } else System.out.println("Please specify IP or domain name!"); } catch (Exception e) { System.err.println("Error message:" + e.getMessage()); } }} In the above, the IP or domain name is passed into the program through the command line parameter, and then the 80 port of the IP or domain name specified through the command line parameter is connected through the Socket socket = new Socket(args[0], 80). Since the Socket class constructor uses throws when defining, when calling the Socket class constructor, you must use the try...catch statement to catch the error, or use the throws statement to throw the error for the main function.
Use the Socket class to connect to the server to determine which ports are opened on a host. The following code is a program that scans which ports are opened in this machine.
2. Send and receive data
The two most important methods in the Socket class are getInputStream and getOutputStream. These two methods are used to obtain InputStream and OutputStream objects for reading and writing data, respectively. The InputStream here reads the data sent by the server program to the client, and the OutputStream is the data that the client wants to send to the server program.
When writing actual network client programs, whether to use getInputStream or getOutputStream, and who to use first and who to use later is determined by the specific application. For example, by connecting to the 80 port (usually the default port used by the HTTP protocol) of the Post and Telecommunications Press website (www.ptpress.com.cn), sending a string, and finally reading the information returned from www.ptpress.com.cn.
package mysocket;import java.net.*;import java.io.*; public class MyConnection2{ public static void main(String[] args) throws Exception { Socket socket = new Socket("www.ptpress.com.cn", 80); // Send data to the server program OutputStream ops = socket.getOutputStream(); OutputStreamWriter opsw = new OutputStreamWriter(ops); BufferedWriter bw = new BufferedWriter(opsw); bw.write("hello world/r/n/r/n"); bw.flush(); // Receive data from the server program InputStream ips = socket.getInputStream(); InputStreamReader ipsr = new InputStreamReader(ips); BufferedReader br = new BufferedReader(ipsr); String s = ""; while((s = br.readLine()) != null) System.out.println(s); socket.close(); }} When writing the above code, you should pay attention to the following two points:
1. In order to improve the efficiency of data transmission, the Socket class does not transmit data every time the write method is called, but writes the data to be transferred into a buffer (the default is 8192 bytes), and then sends the data in this buffer together through the flush method. Therefore, bw.flush(); is necessary.
2. The reason why "/r/n/r/n" is added after Hello World when sending a string is because the HTTP protocol header uses "/r/n/r/n" as the end flag (the detailed content of the HTTP protocol will be explained later). Therefore, by adding "/r/n/r/n" after sending a string, the server program can think that the HTTP header has ended and can be processed. If "/r/n/r/n" is not added, the server program will wait for the end of the HTTP header, that is, "/r/n/r/n". If so, the server program will not send response information to the client, and br.readLine() will be blocked because it cannot be read to respond information until the connection timed out.
3. Turn off the network connection
So far, we have a preliminary understanding of the basic usage methods of the Socket class, but after the Socket class has processed the data, the most reasonable ending method is to use the Socket class's close method to close the network connection. Although the close method has been used in it, the method of closing the network connection is not just the close method. Let's see under what circumstances can Java shut down the network connection.
There are four types of situations that can cause network connections to be closed:
Although all these 4 methods can achieve the same goal, it is best to use the first or second method to close the network connection. This is because the third and fourth methods generally do not close the network connection immediately. If so, for some applications, a large number of useless network connections will be left, which will occupy a large amount of system resources.
After the Socket object is closed, we can use the isClosed method to determine whether a Socket object is in a closed state. However, what is returned by using the isClosed method is the current state of the Socket object. That is, regardless of whether the Socket object has been connected successfully, isClosde returns true as long as it is in the closed state. If you just create an unconnected Socket object, isClose also returns true. As shown in the following code, false will be output.
Socket socket = new Socket();System.out.println(socket.isClosed());
In addition to the isClose method, the Socket class also has an isConnected method to determine whether the Socket object is connected successfully. When you see this name, readers may misunderstand it. In fact, the isConnected method determines not the current connection status of the Socket object, but whether the Socket object has been connected successfully. If it has been successfully connected, even if isClose returns true now, isConnected still returns true. Therefore, to determine whether the current Socket object is in a connected state, the isClose and isConnected methods must be used at the same time, that is, the Socket object is in a connected state only when isClose returns false and isConnected returns true. The following code demonstrates the generation process of various states of the above Socket object.
package mysocket;import java.net.*; public class MyCloseConnection{ public static void printState(Socket socket, String name) { System.out.println(name + ".isClosed():" + socket.isClosed()); System.out.println(name + ".isConnected():" + socket.isConnected()); if (socket.isClosed() == false && socket.isConnected() == true) System.out.println(name + "In connected state!"); else System.out.println(name + "In non-connected state!"); System.out.println(); } public static void main(String[] args) throws Exception { Socket socket1 = null, socket2 = null; socket1 = new Socket("www.ptpress.com.cn", 80); printState(socket1, "socket1"); socket1.getOutputStream().close(); printState(socket1, "socket1"); socket2 = new Socket(); printState(socket2, "socket2"); socket2.close(); printState(socket2, "socket2"); }} After running the above code, the following output will be shown:
socket1.isClosed():false
socket1.isConnected():true
socket1 is in a connected state!
socket1.isClosed():true
socket1.isConnected():true
socket1 is in a non-connected state!
socket2.isClosed():false
socket2.isConnected():false
socket2 is in a non-connected state!
socket2.isClosed():true
socket2.isConnected():false
socket2 is in a non-connected state!
From the output results, it can be seen that after socket1's OutputStream is closed, socket1 is also automatically closed. In the above code, we can see that for a Socket object socket2 that is not connected to the server, its isClosed method is false. If socket2 isClosed method returns true, the close method must be called displayably using socket2.close.
Although most of the time, we can use the Socket class or the close method of the input and output stream to close the network connection, sometimes we only want to close the OutputStream or InputStream, and while closing the input and output stream, we do not close the network connection. This requires the use of two other methods of the Socket class: shutdownInput and shutdownOutput. These two methods only close the corresponding input and output streams, but they do not have the function of closing the network connection at the same time. Like the isClosed and isConnected methods, the Socket class also provides two methods to determine whether the input and output streams of the Socket object are closed. These two methods are isInputShutdown() and isOutputShutdown(). The following code demonstrates the process of closing only input and output streams:
package mysocket;import java.net.*; public class MyCloseConnection1{ public static void printState(Socket socket) { System.out.println("isInputShutdown:" + socket.isInputShutdown()); System.out.println("isOutputShutdown:" + socket.isOutputShutdown()); System.out.println("isClosed:" + socket.isClosed()); System.out.println(); } public static void main(String[] args) throws Exception { Socket socket = new Socket("www.ptpress.com.cn", 80); printState(socket); socket.shutdownInput(); printState(socket); socket.shutdownOutput(); printState(socket); }} After running the above generation, you will get the following output:
isInputShutdown:false
isOutputShutdown:false
isClosed:false
isInputShutdown:true
isOutputShutdown:false
isClosed:false
isInputShutdown:true
isOutputShutdown:true
isClosed:false
From the output results, we can see that the isClosed method always returns false, so it is certain that shutdownInput and shutdownOutput do not affect the status of the Socket object.
I hope this article will be helpful to you. This is all for Java to use Socket class to receive and send data content. I hope everyone will continue to follow our website! If you want to learn Java, you can continue to follow this website.