Java socket practice

Time:2020-5-22

Socket communication based on TCP connection

TCP protocol provides reliable data transmission service by establishing TCP connection. The two ends of a “TCP connection” connection are two processes running on two hosts on the Internet, one is the sending process and the other is the receiving process. Each process is uniquely determined by a socket (IP address and port). A pair of sockets uniquely identifies a TCP connection. TCP connection is full duplex and point-to-point. Full duplex means that data can be transmitted in two directions, and point-to-point means that each TCP connection has only two endpoints.

Java socket practice

A pair of sockets are used for TCP connection. After the connection is successful, byte stream data can be sent or received through the socket to complete point-to-point, full duplex communication.

TCP socket communication in Java

Java socket practice

The server creates theServerSocketObject, call the accept() method to wait for the client connection request, during which the current process is blocked. When the server receives the connection request from the client, the process continues to run and establishes a TCP connection. Accept () completes and returns a socket object, through which the real-time data communication is realized with the socket object of the client.

ServerSocket serverSocket = new ServerSocket(7000);
Socket socket = serverSocket.accept();

The client creates a socket object, specifies the IP and port of the server host, and sends a TCP connection request. After the server accepts the connection request, the socket object is created successfully. At this time, the socket object can communicate with the socket object of the server in real time.

Socket socket = new Socket("127.0.0.1", 7000);

Output / read byte stream data using socket object

Get the input string from the console. The string data will flow from printwriter to outputstreamwriter in the OutputStream of the inflow socket through the link established by TCP to the InputStream of the corresponding socket. Note that sockets are always paired.

PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
message = scanner.nextLine();
writer.println(message);
writer.flush();

In the socket at the other end, the data sent can be read out through InputStream. At this time, the data flow direction is InputStream – > inputstreamreader – > BufferedReader – > console.

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = "";
while ((line = bufferedReader.readLine()) != null) {
        System.out.println(line);
}

The whole data flow is: client console – > printwriter – > outputstreamwriter – > OutputStream of client socket – > TCP link – > InputStream of server Sockt – > inputstreamreader – > BufferedReader – > server console. Socket can easily send data from the client to the server.

Example

After understanding the socekt communication, we can use socket to imitate the QQ group chat effect: when a user sends a message, all users receive the message and display it on the console.

client

The client needs two processes. One process constantly reads the data from the console. When it reads the user’s input, it sends the read data to the server, which is called the write process. Another process receives the data sent by the server and displays it on the console, which is called the read process.

public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        Socket socket = new Socket("127.0.0.1", 7000);

        //Get input and output streams
        PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

        //Enable two threads to read and write respectively
        
        //Write thread
        new Thread(() -> {
            //Loop read data from console
            String message = "";
            while (!message.equals("exit")) {
                message = scanner.nextLine();
                writer.println(message);
                writer.flush();
            }
            writer.close();
        }).start();

        //Read thread
        new Thread(() -> {
            //Keep getting data from input stream
            String line = "";
            try {
                while ((line = bufferedReader.readLine()) != null) {
                    System.out.format("%50s", line);
                    System.out.println();
                }
                bufferedReader.close();
            } catch (IOException e) {

            }
        }).start();

    }

Server

In order to respond to multiple client connections, the accept() method needs to be called continuously in the loop. Whenever a new TCP connection is acquired, the acquired socket object is stored in the set, and a thread is opened for each socket object. The main task is to read data from InputStream continuously, that is, to receive and send client data. After obtaining the data, it is sent to all connected client sockets (except for the client socket that sends the data), that is, it traverses the set to send the data.

public class Server {
    public static int userCount = 0;

    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(7000);
        Set<Socket> socketSet = new HashSet<>();

        while (true) {
            Socket socket = serverSocket.accept();
            socketSet.add(socket);
            userCount++;
            //Start a new thread
            Thread thread = new Thread(() -> {
                //Keep getting data from input stream
                BufferedReader bufferedReader = null;
                try {
                    bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    String userName = Thread.currentThread().getName();
                    String line = "";
                    System.out.println("start Read");
                    while ((line = bufferedReader.readLine()) != null) {
                        System.out.println (username + "message:" + line);
                        for (Socket tem :
                                socketSet) {
                            if (!tem.equals(socket)) {
                                PrintWriter writer = new PrintWriter(new OutputStreamWriter(tem.getOutputStream()));
                                writer.println(line + ":" + userName);
                                writer.flush();
                            }
                        }
                    }
                    bufferedReader.close();
                } catch (IOException e) {
                }
                System.out.println("finish Read");
            });
            thread.setName ("user" + usercount);
            thread.start();
        }

    }
}

Rendering of running at the terminal:
Java socket practice
Java socket practice
Java socket practice