TCP Programming of Network Programming

Keywords: Java socket network Programming

Last article Understanding UDP and TCP is enough. We have a preliminary understanding of network programming, UDP protocol and TCP protocol related content. This connection-oriented TCP protocol must establish a connection with the other party before formal communication, which is modeled according to the telephone system. For example, when you call someone, you have to wait until the line is connected and the other person picks up the microphone to talk to each other. This article explains TCP programming in detail.

Articles Catalogue

How do computers transmit data?

If there are two computers, the data transmission between them is through the seven-layer protocol, the output (computer A) output data through the seven-layer protocol, and the data transmission to the input (computer B) through the seven-layer protocol. As shown in the following figure:

But from the application layer to the transport layer, how does the computer go to which protocol to use, TCP or UDP? In fact, there is a socket between the two layers, through which you can know which protocol to use.

In Java language, TCP network programming provides good support. In actual implementation, java.net.Socket class represents client connection and java.net.ServerSocket class represents server connection. In network programming, the details of the underlying network communication have been highly encapsulated, so when programmers actually program, they only need to specify the IP address and port number to establish the connection.

2. One-way communication

Step 1: Connect
In Java API, the object of java.net.Socket class represents the network connection, so the client network connection is established, that is, the object of Socket type is created. This object represents the network connection. The example is as follows:

     Socket socketA = new Socket("192.168.1.103",8888);

     Socket socketB = new Socket("www.baidu.com",1000);

socketA represents port 8888 connected to a computer with an IP address of 192.168.1.103.
socketB means port 1000 connected to a computer whose domain name is www.baidu.com.

Step 2: Network Data Exchange
In Java language, the data transmission function is implemented by Java IO, that is to say, only the input stream and output stream can be obtained from the connection, and then the data sent will be written to the output stream of the connection object and read from the input stream after the transmission is completed. The sample code is as follows:

OutputStream os = socket1.getOutputStream(); //Obtain the output stream

InputStream is = socket1.getInputStream();     //Get the input stream

Step 3: Close the network, flow

socket1.close();

Example: Client sends information to server

Client:

package com.Stream;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class ClientTest//Client
{
	public static void main(String[] args) throws UnknownHostException, IOException {
		 
		//First step
		Socket client = new Socket("localhost",9999);
		//Step 2
		OutputStream os = client.getOutputStream();
		DataOutputStream dos = new DataOutputStream(os);
    
		dos.writeUTF("Hello");
	
		//Step 3
		client.close();
		os.close();
		dos.close();
	
	}
}

Server side:

package com.Stream;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerTest//Server
{

	public static void main(String[] args) throws IOException
	{
		System.out.println("Server Start————————");
		//Create sockets, specify port numbers
		ServerSocket ss = new ServerSocket(9999); 
		//accept the socket of the server through the method of ServerSocket
		Socket server = ss.accept();
		
		InputStream in = server.getInputStream();
		DataInputStream dis = new DataInputStream(in);
		String str = dis.readUTF();
		System.out.println("The client said: "+ str);
		
		//close resource
		ss.close();
		server.close();
		in.close();
		dis.close();

	}
}

Note that:

  1. Run the server first, then the client
  2. If the Socket client = new Socket("localhost",9999) is created on the client side; when an exception occurs at runtime, the IP address can be changed to localhost.

3. Two-way communication

The above example is just that the client says hello to the server, so it is called one-way communication. In the next example, when the client receives the greeting from the server, it responds to it, which is called two-way communication.

Client:

package com.Stream;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class ClientTest//Client
{
	public static void main(String[] args) throws UnknownHostException, IOException {
		 
		//First step
		Socket client = new Socket("localhost",9999);
		//Step 2
		OutputStream os = client.getOutputStream();
		DataOutputStream dos = new DataOutputStream(os);
    
		dos.writeUTF("Hello");
		
		//Client accepts server-side data (new part)
		client.shutdownOutput();
		InputStream is = client.getInputStream();
		DataInputStream dis = new DataInputStream(is);
		String str=dis.readUTF();
		System.out.println("The server said to me" + str );
	
		//Step 3
		client.close();
		os.close();
		dos.close();
	
	}
}

Server side:

package com.Stream;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerTest//Server
{

	public static void main(String[] args) throws IOException
	{
		System.out.println("Server Start————————");
		//Create sockets, specify port numbers
		ServerSocket ss = new ServerSocket(9999); 
		//accept the socket of the server through the method of ServerSocket
		Socket server = ss.accept();
		
		InputStream in = server.getInputStream();
		DataInputStream dis = new DataInputStream(in);
		String str = dis.readUTF();
		System.out.println("The client said: "+ str);
		
		//Response Client (New Part)
		server.shutdownInput();
		OutputStream ops = server.getOutputStream();
		DataOutputStream dos = new DataOutputStream(ops);
		dos.writeUTF("I'm fine!");
		
		
		//close resource
		ss.close();
		server.close();
		in.close();
		dis.close();

	}

}

4. Simulated landing

Above, we learned how to communicate in two directions. Next, we use two-way communication to simulate the login account.

Basic idea: When landing an account, the password we entered is sent to the server in the form of stream. After receiving our request, the server searches for the existence of such a password pair in its own database. If so, the login succeeds and if not, the login fails.
Question: We need to fill in the account number and password. What form should we use to store the account password entered by the user?
Solution: We can encapsulate the account password as an object and send it to the server through serialization to text. If you don't understand serialization, please refer to the article Serialization and Deserialization of Java Objects

package com.Stream;

import java.io.Serializable;

public class Account implements Serializable
{

	private String username;
	private String password;
	
	
	
	public Account(String username, String password)
	{
		super();
		this.username = username;
		this.password = password;
	}



	public String getUsername()
	{
		return username;
	}



	public void setUsername(String username)
	{
		this.username = username;
	}



	public String getPassword()
	{
		return password;
	}



	public void setPassword(String password)
	{
		this.password = password;
	}


}

Client:

package com.Stream;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class ClientTest
{
	public static void main(String[] args) throws UnknownHostException, IOException {
		 

		Socket client = new Socket("localhost",8888);
		
		//Enter account password from keyboard
		Scanner sc =new Scanner(System.in);
		System.out.print("Please enter username: ");
		String username = sc.next();
		System.out.print("Please enter password: ");
		String password = sc.next();
		
		//Encapsulated as an object
		Account account = new Account(username,password);
		//Data transmission
		OutputStream os = client.getOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(os); //Transferring data using object streaming
		oos.writeObject(account);
		
		//Client receives data
		client.shutdownOutput();
		InputStream in1 = client.getInputStream();
		DataInputStream dis1 = new DataInputStream(in1);
		System.out.println(dis1.readUTF());
		
		
        //close resource
		client.close();
		os.close();
		dis1.close();
		oos.close();
		in1.close();
		sc.close();
	
	}
}

Server side:

package com.Stream;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerTest
{

	public static void main(String[] args) throws IOException, ClassNotFoundException
	{
		
		ServerSocket ss = new ServerSocket(8888);  
		Socket server = ss.accept();
		
		InputStream in = server.getInputStream();
		ObjectInputStream oos = new ObjectInputStream(in);
		Account account = (Account)(oos.readObject()); //Converting Object type to Account type
		
		//Check
		String res = null;
		if((account.getUsername().equals("kevin123")&& (account.getPassword()).equals("123456789"))) {
			res ="Login successful!";
		}else {
			res ="The credentials provided are invalid.";
		}
		//Response Client
		server.shutdownInput();
		OutputStream oos2 = server.getOutputStream();
		DataOutputStream oos3 = new DataOutputStream(oos2);
		oos3.writeUTF(res);
		
		//close resource
		ss.close();
		server.close();
		in.close();
		oos2.close();
		oos3.close();
		oos.close();
	}
}

Landing success:

Landing failure:

5. Use try-catch to catch exceptions

Instead of handling exceptions in the form of thrown exceptions, try-catch-final is used to catch exceptions.
In final, if (xxx! = null) prevents null pointer exceptions

Client

package com.Stream;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class ClientTest
{
	
	public static void main(String[] args) {
		
		Socket client = null;
		OutputStream os = null;
		ObjectOutputStream oos =null;
		InputStream in1 = null;
		DataInputStream dis1 =null;
		
		try
		{
			client = new Socket("localhost",8888);
			//Enter account password from keyboard
			Scanner sc =new Scanner(System.in);
			System.out.print("Please enter username: ");
			String username = sc.next();
			System.out.print("Please enter password: ");
			String password = sc.next();
			sc.close();
			
			//Encapsulated as an object
			Account acc = new Account(username,password);
			//Data transmission
			os = client.getOutputStream();
			oos =new ObjectOutputStream(os); //Transferring data using object streaming
			oos.writeObject(acc);
			
			//Client receives data
			client.shutdownOutput();
			in1=client.getInputStream();
			dis1 =new DataInputStream(in1);
            String result = dis1.readUTF();
            System.out.println(result);
			
			
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}finally {
			 
			try
			{
				if(client != null){
					client.close();
				}	
			}
			catch (IOException e)
			{
				
				e.printStackTrace();
			}
			try
			{
				if(os != null) {
					os.close();
				}
			}
			catch (IOException e)
			{
				
				e.printStackTrace();
			}
			try
			{
				if(dis1 != null) {
					dis1.close();
				}
			}
			catch (IOException e)
			{
				
				e.printStackTrace();
			}
			try
			{
				if(oos!= null) {
					oos.close();
				}
			}
			catch (IOException e)
			{
				
				e.printStackTrace();
			}
			try
			{
				if(in1 != null){
					in1.close();
				}
			}
			catch (IOException e)
			{
			
				e.printStackTrace();
			}
		}
	
	}
}

Server side:

package com.Stream;


import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerTest
{

	public static void main(String[] args) 
	{
		
		ServerSocket ss =null;
		Socket server =null;
		InputStream in = null;
		ObjectInputStream oos = null;
		OutputStream oos2 = null;
		DataOutputStream oos3 = null;
		
		try
		{
			ss = new ServerSocket(8888);
			server = ss.accept();
			
			in = server.getInputStream();
			oos=new ObjectInputStream(in);
			Account account = (Account)(oos.readObject()); //Converting Object type to Account type
			
			//Check
			String res = null;
			if((account.getUsername().equals("kevin123")&& (account.getPassword()).equals("123456789"))) {
				res ="Login successful!";
			}else {
				res ="The credentials provided are invalid.";
			}
			//Response Client
			server.shutdownInput();
			oos2 = server.getOutputStream();
			oos3 =new DataOutputStream(oos2);
			oos3.writeUTF(res);
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		catch (ClassNotFoundException e)
		{
			
			e.printStackTrace();
		}  finally {
			//close resource
			try
			{
				if(ss != null) {
					ss.close();
				}
				
			}
			catch (IOException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try
			{
				if(server != null) {
				server.close();
				}
				
			}
			catch (IOException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try
			{
				if(in != null) {
					in.close();
				}
			}
			catch (IOException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try
			{
				if(oos2 !=null) {
				oos2.close();
				}
				
			}
			catch (IOException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try
			{
				if(oos3 != null) {
				   oos3.close();
				}
			}
			catch (IOException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try
			{
				if(oos !=null) {
				  oos.close();
				}
			}
			catch (IOException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}

	}

}

6. How to make the server support multiple clients working at the same time?

In the example above, if the client enters an account password once, the server shuts down after judging the correct error. In real life, a server should work continuously to support multiple client login operations.

A server generally needs to provide communication for multiple clients at the same time. If you need to support multiple clients at the same time, you must use the thread concept described earlier. Simply put, when the server receives a connection, a special thread is started to process the communication with the client.

Server side:

package com.Stream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class Server
{
	public static void main(String[] args) 
	{
		ServerSocket ss =null;
		Socket server =null;
	
		try
		{
			ss = new ServerSocket(8888);
			
			while(true) {
				
				server = ss.accept();     //Acquisition of client sockets through accept
				
				new ServerThread(server);//Each receive is processed by a thread.
			}
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}  
	}
}

Server-side thread class:

package com.Stream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.net.Socket;

public class ServerThread extends Thread
{
	Socket server =null;
	InputStream in = null;
	ObjectInputStream oos = null;
	OutputStream oos2 = null;
	DataOutputStream oos3 = null;
	


	public ServerThread(Socket server) //Use constructors to correlate two methods
	{
		super();
		this.server = server;
		start();
	}



	@Override
	public void run() {
		
		try
		{
		in = server.getInputStream();
		oos=new ObjectInputStream(in);
		Account account = (Account)(oos.readObject()); //Converting Object type to Account type
		
		//Check
		String res = null;
		if((account.getUsername().equals("kevin123")&& (account.getPassword()).equals("123456789"))) {
			res ="Login successful!";
		}else {
			res ="The credentials provided are invalid.";
		}
		//Response Client
		server.shutdownInput();
		oos2 = server.getOutputStream();
		oos3 =new DataOutputStream(oos2);
		oos3.writeUTF(res);
		}
		
		catch (IOException e)
		{
			e.printStackTrace();
		}
		catch (ClassNotFoundException e)
		{
			
			e.printStackTrace();
		}  finally {
			
			try
			{
				if(in != null) {
				in.close();
				}
			}
			catch (IOException e)
			{
				
				e.printStackTrace();
			}
			try
			{
				if(oos2 != null) {
					oos2.close();
				}
				
			}
			catch (IOException e)
			{
				
				e.printStackTrace();
			}
			try
			{
				if(oos3 != null) {
					oos3.close();
				}
				
			}
			catch (IOException e)
			{
				
				e.printStackTrace();
			}
			try
			{
				if(oos != null) {
					oos.close();
				}
				
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		
	}

}

Client:

package com.Stream;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client
{
	
	public static void main(String[] args) {
		
		Socket client = null;
		OutputStream os = null;
		ObjectOutputStream oos =null;
		InputStream in1 = null;
		DataInputStream dis1 =null;
		
		
		try
		{
			client = new Socket("localhost",8888);
			//Enter account password from keyboard
			Scanner sc =new Scanner(System.in);
			System.out.print("Please enter username: ");
			String username = sc.next();
			System.out.print("Please enter password: ");
			String password = sc.next();
			sc.close();
			
			//Encapsulated as an object
			Account acc = new Account(username,password);
			//Data transmission
			os = client.getOutputStream();
			oos =new ObjectOutputStream(os); //Transferring data using object streaming
			oos.writeObject(acc);
			
			//Client receives data
			client.shutdownOutput();
			in1=client.getInputStream();
			dis1 =new DataInputStream(in1);
            String result = dis1.readUTF();
            System.out.println(result);
			
			
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}finally {
			 
			try
			{
				if(client != null){
					client.close();
				}	
			}
			catch (IOException e)
			{
				
				e.printStackTrace();
			}
			try
			{
				if(os != null) {
					os.close();
				}
			}
			catch (IOException e)
			{
				
				e.printStackTrace();
			}
			try
			{
				if(dis1 != null) {
					dis1.close();
				}
			}
			catch (IOException e)
			{
				
				e.printStackTrace();
			}
			try
			{
				if(oos!= null) {
					oos.close();
				}
			}
			catch (IOException e)
			{
				
				e.printStackTrace();
			}
			try
			{
				if(in1 != null){
					in1.close();
				}
			}
			catch (IOException e)
			{
			
				e.printStackTrace();
			}
		}
	
	}
}

Posted by bdichiara on Fri, 19 Jul 2019 05:07:45 -0700