I'm especially puzzled since what seems to be the relevant line (40 in my BotClient) is identical to Andrew's from this page (line 42 in his BotClient). His passes and mine does not!! Further, so far as I can tell, it works -- an incoming message is printed on the console just as for the regular client.
Stuck. Any help much appreciated.
Addendum: Ran multiple times and worked great. Went away, came back and it won't connect the client (giving the message from Client line 30). I had changed a few things but copied files back from this page, still won't connect. Now I'm really lost. Is there some inconsistent behavior in initialization or between threads? Now it's really beyond me!
package com.codegym.task.task30.task3008;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class Server {
private static Map<String, Connection> connectionMap = new ConcurrentHashMap<>();
public static void main(String[] args) {
System.out.print("Input socket port: ");
int port = ConsoleHelper.readInt();
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("Server is running!");
while (true) {
Socket socket = serverSocket.accept();
Handler handler = new Handler(socket);
handler.start();
}
} catch (Exception e) {
System.out.println(e);
}
}
public static void sendBroadcastMessage(Message message) {
try {
for (Map.Entry<String, Connection> entry : connectionMap.entrySet()) {
entry.getValue().send(message);
}
} catch (IOException e) {
System.out.println("Error, message cannot be sent!");
}
}
private static class Handler extends Thread {
private Socket socket;
public Handler(Socket socket) {
this.socket = socket;
}
public void run() {
String userName = null;
ConsoleHelper.writeMessage("Connection established with " + socket.getRemoteSocketAddress());
try (Connection connection = new Connection(socket)) {
userName = serverHandshake(connection);
sendBroadcastMessage(new Message(MessageType.USER_ADDED, userName));
notifyUsers(connection, userName);
serverMainLoop(connection, userName);
} catch (IOException | ClassNotFoundException e ) {
ConsoleHelper.writeMessage("Error occurred while communicating with the remote address.");
} finally {
if (userName != null) {
connectionMap.remove(userName);
sendBroadcastMessage(new Message(MessageType.USER_REMOVED, userName));
}
}
}
private String serverHandshake(Connection connection) throws IOException, ClassNotFoundException {
while (true) {
connection.send(new Message(MessageType.NAME_REQUEST));
Message response = connection.receive();
if (response.getType().equals(MessageType.USER_NAME)) {
String data = response.getData();
if (data != null && !data.equals("")) {
if (!connectionMap.containsKey(data)) {
connectionMap.put(data, connection);
connection.send(new Message(MessageType.NAME_ACCEPTED));
return data;
}
}
}
}
}
private void notifyUsers(Connection connection, String userName) throws IOException {
for (Map.Entry<String, Connection> entry : connectionMap.entrySet()) {
if (!entry.getKey().equals(userName)) {
connection.send(new Message(MessageType.USER_ADDED, entry.getKey()));
}
}
}
private void serverMainLoop(Connection connection, String userName) throws IOException, ClassNotFoundException {
while (true) {
Message message = connection.receive();
if (message.getType() == MessageType.TEXT) {
Server.sendBroadcastMessage(new Message(MessageType.TEXT, userName + ": " + message.getData()));
} else {
ConsoleHelper.writeMessage("Message not TEXT");
}
}
}
}
}