Thread Pool – Socket in java


Vấn đề được đặc ra ở đây ứng dụng của chúng ta là Client – Server giao tiếp thông qua Socket.

Chúng ta có thể có rất nhiều client truy cập vào server cùng 1 thời điểm điều này có thể dẫn tới có quá nhiều client truy cập cùng 1 lúc sẻ dẫn tới sập hệ thống ( DDOS ) cách tấn công thường dùng nhứt.

Vậy làm sao để ta giới hạn được việc truy cập của người dùng (Client ).

Có nhiều cách thức để chúng ta làm việc như vậy các bạn có thể tham khảo với các từ khóa như Blocking Queues, Thrad-Safe Collection, Executors.

Bài hôm nay mình hướng dẫn các bạn dùng Executors để thạo ra 1 Thread Pool.

Cực kì đơn giản và cực kí hữu ích

  • Chúng ta tạo ra 1 cái Pool có giới thạn với 4 Thread.
  • ExecutorService tasks = Executors.newFixedThreadPool(4);

Để thực hiện 1 Thread chúng ta sẻ gọi tasks.execute(YOUR_RUNNABLE_OR_CALLABLE)

Bài làm củng chúng ta như sau :

Client của chúng ta : Client.java // chúng ta tạo ra 10 Client truy cập vào Server

package com.gcs.client;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {
	private String name = "";

    public Client(String name) {
		this.name = name;
	}

    public void connectServer(String server, int port){
        try {

            Socket s = new Socket(server, port);
            // send data to server
            PrintWriter writer = new PrintWriter(s.getOutputStream(),true);
            writer.println(name);

            s.close();

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

    }

	public static void main(String[] args) {
        for(int i=1; i<=10; i++){
        	Client client = new Client("Client " +i);
        	client.connectServer("127.0.0.1", 8989);
        }

    }
}

Đây là Server của chúng ta Server.java – Tạo ra thread 4 chỉ cho phép 4 client truy cập tại 1 thời điểm

package com.gcs.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Server {

    public static void main(String[] args) {
        Server myServer = new Server();
        myServer.publicServer();
    }

    public void publicServer(){
        try {
            ServerSocket serverSocket = new ServerSocket(8989);
            System.out.println("Server start connect.....");
            ExecutorService tasks = Executors.newFixedThreadPool(4);

            while(true){
                Socket sock = serverSocket.accept();                
                tasks.execute(new HandlerClient(sock));                                            
            }
        } catch (IOException e) {           
            e.printStackTrace();
        }
    }

}

Đây là Class handlerClient.java – Mục đích Thread ở đây mình sẻ cho nó ngủ vào 1 tham số Random

package com.gcs.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.Random;

public class HandlerClient implements Runnable{
	Socket socket;
	BufferedReader reader;
	//static Logger logger = Logger.getLogger(HandlerClient.class);
	public HandlerClient(Socket socket) {	
		//PropertyConfigurator.configure("log4j.properties");
		try {
			this.socket = socket;
			reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		} catch (IOException e) {
			e.printStackTrace();
		}   
	}

	public void run() {
		// do something	with sockets
		try {
			String clientSend = reader.readLine();
			while(true){
				// process every thing and out
				int sleepSecond = new Random().nextInt(5000);
				System.out.println(clientSend + " is running...");
				//logger.info(clientSend + " is running...");
				pauseProcessSomeThing(sleepSecond);				
				break; // condition for we known ..Thread worked.
			}
			//logger.info("\t" + clientSend + " is finished...");
			System.err.println("\t" + clientSend + " is finished...");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void pauseProcessSomeThing(int milis){
		try {
			Thread.sleep(milis);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

Nếu ai dùng Log4j để in ra kết quả thì các bạn có thể bỏ đi các comment
Kết quả khi run:
d1

Chúng ta thấy. Bắt đầu là Client 1-2-3-4. Khi [1 -OUT] thì có Thread 5 bước vào.
Khi đó trong Pool của chúng ta sẻ có thread 2-3-4-5 Tiếp tục [3-Out] [6-In] => Pool có 2-4-5-6…so on.
Cuối cùng pool còn lại các thread 6-7-8-10.

Một kết quả khác khi mình run lần 2 cho ai dùng Log4j
d1

Chúc các bạn thành công .

One Response to “Thread Pool – Socket in java”

  1. kobee Says:

    You have several options to accelerate the communication between sockets. This issue will be also one of my posted Principles Of Operation. First of all, communication is dual -also both sides must obey the rules, otherwise it’s useless to tune only one side while the other side stands lazy around.:-o
    – setTcpNoDelay(true): tells the socket to send the buffer immediately without waiting for “full”
    – setSendBuffer(), setReceiveBuffer(): give JVM to allocate an amount of bytes for storing data. For 200MB you can have, for example, 1MB or setSendBuffer(1048576) if your computer has more than 2GB RAM
    – Use the fastest IO of Socket. They’re the InputStream and OutputStream, DON’T wrap other layer(s) around these IO streams.
    – Use the method read(byte[], 0, n) or write(byte[], 0, n). Not the read(byte[]) or write([]).
    – flush() only after the last write().


Leave a comment