Fundamentals of java socket network programming

network model

Difference between TCP protocol and UDP protocol

The underlying implementation principle of Http protocol.

What is a network model

The essence of network programming is the data exchange between two devices. Of course, in computer network In, equipment mainly refers to computers. Data transmission itself is not very difficult, that is, send the data from one device to another device, and then accept the data fed back by another device.

Current network programming is basically based on request / response mode, that is, one device sends request data to another, and then receives feedback from another device.

In network programming, the program that initiates the connection, that is, the program that sends the first request, is called the client, and the program waiting for other programs to connect is called the server. The client program can be started when needed, while the server needs to be started all the time in order to connect at the same time. For example, taking a call as an example, the person who dials first is similar to the client, and the person who answers the call must keep the phone unblocked, similar to the server.

Once the connection is established, the client and server can transfer data, and their identities are equivalent.

In some programs, the program has both client-side and server-side functions. The most common software is BT and emule.

Let's talk about how to establish a connection and how to send data.

IP address and domain name

In real life, if you want to make a phone call, you need to know the telephone number of the corresponding person, and if you want to send a letter, you need to know the address of the recipient. The same is true in the network. If you need to know the location of a device, you need to use the IP address of the device. The specific connection process is implemented by hardware, and programmers don't need to care too much.

IP address is a rule. Now IPv4 is used, which is composed of four numbers between 0-255. It only needs 4 bytes when stored in the computer. In a computer, IP addresses are assigned to network cards. Each network card has a unique IP address. If a computer has multiple network cards, the computer has multiple different IP addresses. Within the same network, the IP addresses cannot be the same. The concept of IP address is similar to that of telephone number and ID card.

Because the IP address is not easy to remember, the concept of domain name has been specially created. In fact, it is to give the IP a character name, such as 163.com, sina.com, etc. There is a certain correspondence between IP and domain name. If you compare the IP address to the ID number, then the domain name is your name.

In fact, only IP addresses can be used for data transmission in the network, so before transmission, the domain name needs to be converted to IP, which is specially completed by the server called DNS.

Therefore, in network programming, you can use IP or domain name to identify a device on the network.

Port concept

In order to run multiple programs on one device, the concept of port is artificially designed. A similar example is the extension number within the company.

It is specified that a device has 216 ports, that is, 65536 ports, and each port corresponds to a unique program. Each network program, whether client or server, corresponds to one or more specific port numbers. Due to multiple errors between 0-1024 operating system Occupation, so the port number after 1024 is generally used in actual programming.

Using the port number, you can find the only program on a device.

Therefore, if you need to establish a connection with a computer, you only need to know the IP address or domain name, but if you want to exchange data with a program on the computer, you must also know the port number used by the program.

Summary

Network programming is to use IP address, domain name and port to connect to the corresponding program on another computer to exchange data according to the specified protocol (data format). In actual programming, the establishment of connection, sending and receiving data have been realized at the language level. More work is to design the protocol and write the code for generating and parsing data, Then convert the data into a logical structure to display or control logic.

  For beginners or programmers who have not been in contact with network programming, they will feel that the knowledge involved in network programming is very deep and difficult. In fact, this is a misunderstanding. When you are familiar with the grammar, the basic network programming has been implemented very simply.

Network model diagram

Getting started with Socket

What is a Socket?

Socket is a mechanism for network services.

Sokcet on both ends of the communication

Network communication is actually the communication between Sokcet

Data is transferred between two sokcets via IO.

Conceptual differences between TCP and UDP:

udp: a. for connectionless, encapsulate the data and source into data packets without establishing a connection

    b. The size of each datagram is within the limit of 64k

    c. Because there is no connection, it is an unreliable protocol

    d. No need to establish a connection, fast

tcp: A. It is recommended to connect to form a data transmission channel

    b. A large amount of data is transmitted in the connection in the form of byte stream

    c completes the connection through three handshakes, which is a reliable protocol

    d connection must be established, and m efficiency will be slightly lower

   

UDP protocol

The course case is realized through UDP protocol, and the client and server are transmitted

UDP server side code

//socket server
class UdpSocketServer {

	public static void main(String[] args) throws IOException {
		System.out.println("udp Server side start connection....");
		DatagramSocket ds = new DatagramSocket(8080);
		byte[] bytes = new byte[1024];
		DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
		// Blocking, waiting to accept the request sent by the client
		ds.receive(dp);
		System.out.println("source:"+dp.getAddress()+",Port number:"+dp.getPort());
		// Get client request content
		String str=new String(dp.getData(),0,dp.getLength());
		System.out.println("str:"+str);
		ds.close();
	}

}

  UDP client code

// udp client code
public class UdpClient {

	 public static void main(String[] args) throws IOException {
		 System.out.println("udp Client initiated connection....");
		 DatagramSocket ds = new DatagramSocket();
		 String str="Yang reform";
		 byte[] bytes= str.getBytes();
		 DatagramPacket dp= new DatagramPacket(bytes, bytes.length,InetAddress.getByName("127.0.0.1"),8080);
		 ds.send(dp);
		 ds.close();
	}
	
}

TCP protocol

TCP handshake protocol
In TCP/IP protocol, TCP protocol uses three handshakes to establish a connection.  
First handshake: when establishing a connection, the client sends a SYN packet (SYN=J) to the server and enters SYN_SEND status, waiting for server confirmation;  
The second handshake: when the server receives the SYN packet, it must confirm the SYN of the customer (ACK=J+1), and also send a SYN packet (SYN=K), that is, SYN+ACK packet. At this time, the server V status;  
The third Handshake: the client receives the SYN + ACK packet from the server and sends the confirmation packet ACK(ACK=K+1) to the server. After the packet is sent, the client and the server enter the ESTABLISHED state and complete the three handshakes.
After three handshakes, the client and server start transmitting data,

 

Four breakups:
Since TCP connections are full duplex, each direction must be closed separately. This principle is that when one party completes its data transmission task, it can send a FIN to terminate the connection in this direction. Receiving a FIN only means that there is no data flow in this direction. A TCP connection can still send data after receiving a FIN. The party that first performs the shutdown will perform the active shutdown and the other party will perform the passive shutdown.
(1) Client A sends A FIN to close the data transmission from client A to server B.
(2) Server B receives this FIN and sends back an ACK. The confirmation sequence number is the received sequence number plus 1. Like SYN, a FIN will occupy a sequence number.
(3) Server B closes the connection with client A and sends A FIN to client A.
(4) Client A sends back ACK message confirmation and sets the confirmation sequence number to the received sequence number plus 1.

 

1. Why does establishing a connection protocol involve three handshakes, while closing a connection involves four handshakes?
    This is because when the SOCKET in LISTEN status of the server receives the connection establishment request of SYN message, it can send ACK and SYN (ACK plays the role of response and SYN plays the role of synchronization) in one message.

But when you close the connection, when you receive the FIN message notification from the other party, it only means that the other party has no data to send to you; However, you may not send all your data to the other party, so you may not close SOCKET immediately, that is, you may need to send some data to the other party and then send FIN message to the other party to indicate that you agree that you can close the connection now, so the ACK message and FIN message here are sent separately in most cases

2. Why TIME_WAIT for 2MSL before returning to CLOSED status?

This is because although both parties agree to close the connection, and the four handshake messages are coordinated and sent, it is reasonable to directly return to the CLOSED state (just like from SYN_SEND state to ESTABLISH state); However, because we must assume that the network is unreliable, you can't guarantee that the ACK message you sent last will be received by the other party, so the other party is in the last position_ SOCKET in ack status may retransmit FIN message because it does not receive ACK message due to timeout, so this time_ The wait status is used to retransmit ack messages that may be lost.

Server side code

1. Why does establishing a connection protocol involve three handshakes, while closing a connection involves four handshakes?
    This is because when the SOCKET in LISTEN status of the server receives the connection establishment request of SYN message, it can send ACK and SYN (ACK plays the role of response and SYN plays the role of synchronization) in one message.

But when you close the connection, when you receive the FIN message notification from the other party, it only means that the other party has no data to send to you; However, you may not send all your data to the other party, so you may not close SOCKET immediately, that is, you may need to send some data to the other party and then send FIN message to the other party to indicate that you agree that you can close the connection now, so the ACK message and FIN message here are sent separately in most cases

2. Why TIME_WAIT for 2MSL before returning to CLOSED status?

This is because although both parties agree to close the connection, and the four handshake messages are coordinated and sent, it is reasonable to directly return to the CLOSED state (just like from SYN_SEND state to ESTABLISH state); However, because we must assume that the network is unreliable, you can't guarantee that the ACK message you sent last will be received by the other party, so the other party is in the last position_ SOCKET in ack status may retransmit FIN message because it does not receive ACK message due to timeout, so this time_ The wait status is used to retransmit ack messages that may be lost.

Server side code

//tcp server side
class TcpServer {

	public static void main(String[] args) throws IOException {
		System.out.println("socket tcp Server side startup....");
		ServerSocket serverSocket = new ServerSocket(8080);
		// Waiting for client requests
		Socket accept = serverSocket.accept();
		InputStream inputStream = accept.getInputStream();
		// Convert to string type
		byte[] buf = new byte[1024];
		int len = inputStream.read(buf);
		String str = new String(buf, 0, len);
		System.out.println("The server accepts client content:" + str);
		serverSocket.close();
	}
}

Client code

public class TcpClient {
	public static void main(String[] args) throws UnknownHostException, IOException {
		System.out.println("socket tcp Client startup....");
		Socket socket = new Socket("127.0.0.1", 8080);
		OutputStream outputStream = socket.getOutputStream();
		outputStream.write("I'm Yang reform".getBytes());
		socket.close();
	}
}

BIO and NIO

The difference between IO(BIO) and NIO: its essence is the difference between blocking and non blocking

Blocking concept: when an application obtains network data, if the network transmits data very slowly, it will wait until the transmission is completed.

Non blocking concept: applications can get ready data directly without waiting.

IO is in the form of synchronous blocking and NIO is in the form of synchronous non blocking. NIO does not realize asynchronous. After JDK1.7, NIO library package is upgraded to support asynchronous non blocking

Classmate model NIO2.0(AIO)

BIO: synchronous blocking IO. The server implementation mode is one thread per connection, that is, when the client has a connection request, the server needs to start a thread for processing. If the connection does not do anything, it will cause unnecessary thread overhead. Of course, it can be improved through the thread pool mechanism.  
NIO: synchronous non blocking IO. The server implementation mode is one request and one thread, that is, the connection requests sent by the client will be registered on the multiplexer. The multiplexer will start a thread for processing only when it polls that there are I/O requests connected.  
AIO(NIO.2): asynchronous non blocking IO. The server implementation mode is one valid request and one thread. The I/O requests of the client are completed by the OS first, and then notify the server application to start the thread for processing.  

During synchronization, the application will directly participate in IO read and write operations, and our application will directly block a method until the data is ready:

Or use the strategy of rotation training to check the ready status of data in real time, and obtain data if ready

When asynchronous, all IO read and write operations are handed over to the operating system, which is not directly related to our application. Our program does not need relational IO read and write

When the system completes the IO read-write operation, it will send a notification to our application, and our application can directly take away the data pole.

Support multiple requests using multithreading

The server implementation mode is one thread per connection, that is, when the client has a connection request, the server needs to start a thread for processing. If the connection does not do anything, it will cause unnecessary thread overhead. Of course, it can be improved through the thread pool mechanism

//tcp server side
class TcpServer {

	public static void main(String[] args) throws IOException {
		System.out.println("socket tcp Server side startup....");
		ServerSocket serverSocket = new ServerSocket(8080);
		// Waiting for client requests
		try {
			while (true) {
				Socket accept = serverSocket.accept();
				new Thread(new Runnable() {

					@Override
					public void run() {
						try {
							InputStream inputStream = accept.getInputStream();
							// Convert to string type
							byte[] buf = new byte[1024];
							int len = inputStream.read(buf);
							String str = new String(buf, 0, len);
							System.out.println("The server accepts client content:" + str);
						} catch (Exception e) {
							// TODO: handle exception
						}

					}
				}).start();

			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			serverSocket.close();
		}

	}

}

public class TcpClient {
	public static void main(String[] args) throws UnknownHostException, IOException {
		System.out.println("socket tcp Client startup....");
		Socket socket = new Socket("127.0.0.1", 8080);
		OutputStream outputStream = socket.getOutputStream();
		outputStream.write("I'm Yang reform".getBytes());
		socket.close();
	}
}

Managing threads using thread pools

//tcp server side
class TcpServer {
     
	public static void main(String[] args) throws IOException {
		ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
		System.out.println("socket tcp Server side startup....");
		ServerSocket serverSocket = new ServerSocket(8080);
		// Waiting for client requests
		try {
			while (true) {
				Socket accept = serverSocket.accept();
				//Using threads
				newCachedThreadPool.execute(new Runnable() {

					@Override
					public void run() {
						try {
							InputStream inputStream = accept.getInputStream();
							// Convert to string type
							byte[] buf = new byte[1024];
							int len = inputStream.read(buf);
							String str = new String(buf, 0, len);
							System.out.println("The server accepts client content:" + str);
						} catch (Exception e) {
							// TODO: handle exception
						}

					}
				});
				

			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			serverSocket.close();
		}

	}

}

public class TcpClient {
	public static void main(String[] args) throws UnknownHostException, IOException {
		System.out.println("socket tcp Client startup....");
		Socket socket = new Socket("127.0.0.1", 8080);
		OutputStream outputStream = socket.getOutputStream();
		outputStream.write("I'm Yang reform".getBytes());
		socket.close();
	}
}

Keywords: Java udp TCP/IP

Added by silversinner on Tue, 05 Oct 2021 00:21:02 +0300