Cần giúp đỡ giải quyết vấn đề về socket java

em được mentor giao cho phần socket tcp/ip với tư duy giải quyết lỗi trùng lặp tin nhắn khi user A đang load lịch sử mà có tin nhắn tới từ user B

Lỗi sẽ xảy ra như nào ?

  • khi User A đang load lịch sử thì server sẽ gửi các tin nhắn cũ về cho User A , mỗi lần load là 15 tin . Ví dụ , tới tin nhắn đang gửi về là tin thứ 10 thì User B gửi một tin tới cho User A thì lúc này 10 tin đã load + 1 tin mới từ User B chen vào + 5 tin nhắn lịch sử cũ load nốt = 16 tin -> lúc này gọi là lỗi trùng lặp tin nhắn

Hướng giải quyết :

  1. Phía client sẽ có 2 luồng chạy cùng lúc là output và input
  • vì đây là thí nghiệm để rõ vấn đề nên nếu client nhập ở console là “1” thì là yêu cầu load lịch sử về

  • khi server nhận được tín hiệu load lịch sử sẽ làm việc và gửi các tin lịch sử về

  • quan trọng ở phần input của phía client , em đã config chính ở đoạn này , nếu HistoryDataManager.getInstance().getHistoryDataState().equals(HistoryDataState.LOADING)

là singleTon chứa ENUM STATE đang loading thì các tin tới khác sẽ nằm trong

BufferedReader inFromServer = socketInputReader.getData(socket)

các tin nhắn tới nằm trong buffer của socket , khi chạy xong thì set ENUM STATE kia về trạng thái nghỉ và các tin nhắn tới từ User B sẽ được load theo đúng thự tự

thế nhưng anh mentor bảo còn nhiều vấn đề phải xem lại , hiện tại những vấn đề em cần phải xem lại sẽ là gì ạ mọi người ?

đây là class Output tới server và gửi tín hiệu load lịch sử

public class OutputDataToServer {
private SocketDataOutput socketDataOutput;
private UserInputReceiver userInputReceiver;

public OutputDataToServer(SocketDataOutput socketDataOutput, UserInputReceiver userInputReceiver) {
    this.socketDataOutput = socketDataOutput;
    this.userInputReceiver = userInputReceiver;
}

public void sendData(Socket serverSocket) throws IOException {
    BufferedReader userInput = userInputReceiver.getData();
    while (true) {
        String messageToSend = UserNameManager.getInstance().getUsername() + " : " + userInput.readLine();
        if (messageToSend.contains("1")) {
            HistoryDataManager.getInstance().setHistoryDataState(HistoryDataState.LOADING);
            messageToSend = UserNameManager.getInstance().getUsername() + " : - request history data";
        }
        socketDataOutput.sendData(serverSocket, messageToSend);
    }
}

}

đây là class OutputDataToClient sau khi nhận được tín hiệu từ input và server sẽ output theo yêu cầu

public class OutputDataToClient {
private SocketDataOutput socketDataOutput;
private ReadLogServer readLogServer;
private Data data;

public OutputDataToClient(SocketDataOutput socketDataOutput, ReadLogServer readLogServer, Data data) {
    this.socketDataOutput = socketDataOutput;
    this.readLogServer = readLogServer;
    this.data = data;
}
public void sendData(Socket clientSocket, BufferedReader inFromClient) {
    String messageFromClient;

    try {
        while ((messageFromClient = inFromClient.readLine()) != null) {

            System.out.println(messageFromClient);

            if (messageFromClient.contains("- request history data")) {
                List<String> listChatHistory = readLogServer.read(data);
                for (String message : listChatHistory) {
                    socketDataOutput.sendData(clientSocket, "Old message ( " + message + " ) - total message " + listChatHistory.size());
                }

            } else {
                for (Socket socket : Data.getClientSockets()) {
                    if (socket != clientSocket) {
                        socketDataOutput.sendData(socket, messageFromClient);
                    }
                }
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

}

đây là class input from server của phía client , tiếp nhận dữ liệu kèm với các điều kiện nếu có tín hiệu load lịch sử

public class InputDataFromServer {
private BufferedReader inFromServer;
private SocketInputReader socketInputReader;
private ParseString parseString;
public InputDataFromServer(SocketInputReader socketInputReader) {
    this.socketInputReader = socketInputReader;
    this.parseString = new ParseStringImplementation();
}

public void receiveData(Socket socket) throws IOException {
    inFromServer = socketInputReader.getData(socket);
    new Thread(() -> {
        try {
            String messageFromServer;
            List<String> list = new ArrayList<>();
            int sizeHistoryData = 0;
            while ((messageFromServer = inFromServer.readLine()) != null) {
                if (HistoryDataManager.getInstance().getHistoryDataState().equals(HistoryDataState.LOADING)) {

                    sizeHistoryData = parseString.getSize(messageFromServer, " - total message ");

                    messageFromServer = parseString.removeText(messageFromServer, " - total message ");

                    if (messageFromServer.contains(UserNameManager.getInstance().getUsername())) {
                        String userName = UserNameManager.getInstance().getUsername();
                        messageFromServer = messageFromServer.replaceFirst(userName + " : ", "");
                    }

                    list.add(messageFromServer);
                    if (list.size() == sizeHistoryData) {
                        for (int i = 0; i < list.size(); i++) {
                            Thread.sleep(1000);
                            System.out.println(list.get(i));
                        }
                        HistoryDataManager.getInstance().setHistoryDataState(HistoryDataState.NO_LOADING);
                        list.clear();
                    }
                } else if (HistoryDataManager.getInstance().getHistoryDataState().equals(HistoryDataState.NO_LOADING)) {
                    if (list.isEmpty()) {
                        if (messageFromServer.contains(UserNameManager.getInstance().getUsername())) {
                            String userName = UserNameManager.getInstance().getUsername();
                            messageFromServer = messageFromServer.replaceFirst(userName + " : ", "");
                        }
                        System.out.println(messageFromServer);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }).start();
}

}

Link github :

Boy, you produce a big package with numerous little APIs woven together and you really expect people to take the time to read them and figure out your “other problems” as your mentor said? Also, I don’t see any reason why you need to create so many little APIs that can each be solved as a method so that your app is cleaner and easier to read and you can see where and how to synchronize them. Maybe this is one of the “little problems” your mentor mentioned.

mình thấy bạn lưu trên file , mà việc đọc ghi trên file ko biết có hỗ trợ đa luồng không, hay bị khóa, chưa kể phải xử lý việc đọc ghi đồng thời, nên việc ông này đang đọc , ông kia ghi vào thành ra sai , đây cũng là 1 trong những lỗi mà các hệ quản trị csdl họ đã giải quyết ,

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?