Java Socket realizes multi-thread communication based on TCP

1 Introduction to TCP

TCP (Transmission Control Protocol) is a connection-oriented, reliable, byte stream-based transport layer communication protocol, defined by IETF's RFC 793. In the simplified OSI model of computer network, it completes the functions specified by the fourth layer of transport layer. User Datagram Protocol (UDP, will be implemented in the next blog) is another important transport protocol within the same layer. In the Internet protocol suite, the TCP layer is an intermediate layer above the IP layer and below the application layer. Reliable, pipe-like connections are often required between application layers of different hosts, but the IP layer does not provide such a streaming mechanism, but provides unreliable packet exchange.
The application layer sends a data stream represented by 8-bit bytes for Internet transmission to the TCP layer, and then TCP partitions the data stream into segments of appropriate length (usually controlled by the data link layer of the network to which the computer is connected). Maximum Transmission Unit (MTU) limit). Then TCP passes the result packet to the IP layer, which transmits the packet through the network to the TCP layer of the receiving entity. In order to ensure that no packet loss occurs, TCP gives each packet a sequence number, and the sequence number also ensures the orderly reception of packets transmitted to the receiving entity. The receiving entity then sends back a corresponding acknowledgment (ACK) for the successfully received packet; if the sender entity does not receive an acknowledgment within a reasonable round-trip delay (RTT), then the corresponding packet is assumed to have been Losses will be retransmitted. TCP uses a checksum function to check data for errors; checksums are calculated both when sending and receiving.
The classes that implement network communication based on the TCP protocol include the Socket class on the client side and the ServerSocket class on the server side.

2 TCP programming through Socket

2.1 Server-side routines

(1) Create a ServerSocket object and bind the listening port.
(2) Monitor client requests through the accept() method.
(3) After the connection is established, the request information sent by the client is read through the input stream.
(4) Send response information to the client through the output stream.
(5) Close the resource of the response.

2.2 Client Routines

(1) Create a Socket object and specify the address and port number of the server to be connected.
(2) After the connection is established, the request information is sent to the server through the output stream.
(3) Obtain the server response information through the input stream.
(4) Close the corresponding resources.

2.3 Multi-threaded implementation of communication steps between server and multi-client

(1) The server side creates a ServerSocket and calls accept() in a loop to wait for the client to connect.
(2) The client creates a socket and requests a connection with the server.
(3) The server accepts the client request, creates a socket and establishes a dedicated line connection with the client.
(4) The two sockets that establish the connection talk on a separate thread.
(5) The server continues to wait for a new connection.

3 code implementation

(1) Create a processing thread class
ServerThread Here, we choose to implement the runnable interface instead of inheriting Thread because a class can only inherit one parent class. When I need to inherit other classes, the parent class is not easy to handle.

package com.socket.test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;

public class ServerThread implements Runnable{

    Socket socket = null;//和本线程相关的Socket
    public ServerThread(Socket socket) {
    this.socket = socket;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        InputStream is = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        OutputStream os = null;
        PrintWriter pw = null;
        try {
            //与客户端建立通信,获取输入流,读取取客户端提供的信息
            is = socket.getInputStream();
            isr = new InputStreamReader(is,"UTF-8");
            br = new BufferedReader(isr);
            String data = null;
            while((data=br.readLine()) != null){//循环读取客户端的信息
                System.out.println("我是服务器,客户端提交信息为:"+data);
            }
            socket.shutdownInput();//关闭输入流

            //获取输出流,响应客户端的请求
            os = socket.getOutputStream();
            pw = new PrintWriter(os);
            pw.write("服务器端响应成功!");
            pw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭资源即相关socket
            try {
                if(pw!=null)
                    pw.close();
                if(os!=null)
                    os.close();
                if(br!=null)
                    br.close();
                if(isr!=null)
                    isr.close();
                if(is!=null)
                    is.close();
                if(socket!=null)
                    socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }
}

(2) Create a server-side class
to use while to listen to the connection requests of different clients in a loop. Because this is an infinite loop, there is no need to close and no chance to close the serverSocket. Set the count value to record the number of times the server has been connected and display the ip value of the client. If the thread processing class inherits the Thread class, then the code to create a new thread can be changed to ServerThread serverThread = new ServerThread(socket);serverThread.start();

package com.socket.test;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

    public static void main(String[] args) {
        try{
            //创建一个服务器端的Socket,即ServerSocket,绑定需要监听的端口
            ServerSocket serverSocket = new ServerSocket(8089);
            Socket socket = null;
            //记录连接过服务器端的数量
            int count=0;
            System.out.println("***服务器即将启动,等待客户端的连接***");
            while(true){//循环侦听新的客户端的连接
                //调用accept()方法侦听,等待客户端的连接以获取Socket实例
                socket = serverSocket.accept();
                //创建新线程
                Thread thread = new Thread(new ServerThread(socket));
                thread.start();

                count++;
                System.out.println("服务器端被连接过的次数:"+count);
                InetAddress address = socket.getInetAddress();
                System.out.println("当前客户端的IP为:"+address.getHostAddress());
            }
        }catch(IOException e){
            e.printStackTrace();
        }
    }

}

(3) Create a client class
In the closing resources later, I annotated the input and output related streams closed, because for the same Socket, the input and output streams are also closed when the socket is closed, and the socket can be closed directly, of course. Reservation is also possible.

package com.socket.test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {

    public static void main(String[] args) {
         try {
                //创建客户端Socket,指定服务器地址和端口
                Socket socket = new Socket("localhost", 8089);
                //建立连接后,获取输出流,向服务器端发送信息
                OutputStream os = socket.getOutputStream();
                //输出流包装为打印流
                PrintWriter pw = new PrintWriter(os);
                //向服务器端发送信息
                pw.write("你好");//写入内存缓冲区
                pw.flush();//刷新缓存,向服务器端输出信息
                socket.shutdownOutput();//关闭输出流

                //获取输入流,接收服务器端响应信息
                InputStream is = socket.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                String data = null;
                while((data=br.readLine())!= null){
                    System.out.println("我是客户端,服务器端提交信息为:"+data);
                }

                //关闭其他资源
                //br.close();
                //is.close();
                //pw.close();
                //os.close();
                socket.close();

            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

    }

}

Run the server side first, then run the client side, the effect will be displayed
write picture description here
References :
http://www.cnblogs.com/alimjan/p/7708892.html
https://www.cnblogs.com/zhaozihan/archive/2016/11/ 12/6057118.html

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325449264&siteId=291194637