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 :
- 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 :