Hallo Leute,
wie man im Titel schon erkennen kann, habe ich ein semantisches Problem in meinem Code.
Ich habe zwar schon versucht, per Debugging dahinter zu kommen, konnte es aber leider selber nicht lösen, weshalb ich mich nun an euch wende.
Es geht um ein kleine Chat-Programm, was ich momentan entwickle. Später wird es ein Instant-Messenger, welcher alle Nachrichten verschlüsselt überträgt, momentan ist es aber "nur" ein Global-Chat, in dem alle gesendeten Nachrichten bei jedem Client landen. Natürlich möchte ich, dass die anderen sehen, wer welche Nachricht versendet hat. Allerdings wird immer "null" als Name angezeigt.
Und damit sind wir auch schon mitten im Problem. Ich kann mir nicht erklären, warum er nicht den richtigen Namen aus der HashMap zieht, sondern "null".
Um diesen Code geht es:
TextSenderServer.java
ClientHandler.java
Habe jetzt mal den kompletten Server-Code gepostet, da da (noch) keine großen Geheimnisse drinstecken. Ich hoffe, es ist nicht all zu unübersichtlich.
Sicher sind da noch einige unschöne Sachen wie viel zu viele Statics drin, aber darum soll's jetzt erst einmal nicht gehen, sondern um den oben beschriebenen Semantik-Fehler.
Falls ihr den Server nicht auf dem eigenen Rechner laufen lassen wollt, passt einfach im Client bei der Verbindung das "localhost" auf "dream-code.net" an, dort läuft der Server immer in der aktuellsten Version.
Vielen Dank schon einmal!
wie man im Titel schon erkennen kann, habe ich ein semantisches Problem in meinem Code.
Ich habe zwar schon versucht, per Debugging dahinter zu kommen, konnte es aber leider selber nicht lösen, weshalb ich mich nun an euch wende.
Es geht um ein kleine Chat-Programm, was ich momentan entwickle. Später wird es ein Instant-Messenger, welcher alle Nachrichten verschlüsselt überträgt, momentan ist es aber "nur" ein Global-Chat, in dem alle gesendeten Nachrichten bei jedem Client landen. Natürlich möchte ich, dass die anderen sehen, wer welche Nachricht versendet hat. Allerdings wird immer "null" als Name angezeigt.
Und damit sind wir auch schon mitten im Problem. Ich kann mir nicht erklären, warum er nicht den richtigen Namen aus der HashMap zieht, sondern "null".
Um diesen Code geht es:
TextSenderServer.java
Java:
package de.mrpixeldream.beta.textsender.server;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Random;
import de.mrpixeldream.beta.textsender.server.handler.ClientHandler;
public class TextSenderServer
{
static int port;
static FileWriter logger;
static HashMap<String, Socket> clients;
static HashMap<String, String> names;
static public HashMap<InetAddress, String> ips;
static HashMap<String, String> ids;
static Random idGenerator;
static ServerSocket server;
public static void main(String[] args)
{
File logfile = new File("logfile.log");
System.out.println("Welcome to ChatBase chat server! The small chat solution.");
System.out.println("Setting up variables...");
clients = new HashMap<String, Socket>();
names = new HashMap<String, String>();
ips = new HashMap<InetAddress, String>();
ids = new HashMap<String, String>();
System.out.println("Done. Creating logger...");
try
{
logger = new FileWriter(logfile, true);
}
catch (Exception e)
{
e.printStackTrace();
}
System.out.println("Logger created, events are logged now.");
if (args.length == 1)
{
port = Integer.parseInt(args[0]);
try
{
log("Set port to " + port);
System.out.println("Server port: " + port);
}
catch (Exception e)
{
e.printStackTrace();
}
}
else
{
port = 22558;
try
{
log("Set port to " + port);
System.out.println("Server port: " + port);
}
catch (Exception e)
{
e.printStackTrace();
}
}
log("Creating socket...");
System.out.println("Creating socket...");
try
{
server = new ServerSocket(port);
System.out.println("Server now listening for new connections...");
while (true)
{
Socket client;
client = server.accept();
System.out.println("Connected from " + client.getInetAddress());
new ClientHandler(client).start();
}
}
catch (IOException e)
{
e.printStackTrace();
log("Got error while creating socket:");
log(e.getMessage());
}
try
{
System.out.println("Closing logger...");
logger.flush();
logger.close();
System.out.println("Closed. Server shutting down!");
}
catch (Exception ex)
{
System.err.println("Logger not closed properly.");
}
}
private static String datePrefix()
{
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd | HH:mm:ss");
Date currentTime = new Date(System.currentTimeMillis());
return "[" + format.format(currentTime) + "]: ";
}
public static void log(String msg)
{
try
{
logger.write(datePrefix() + msg + "\n\n");
logger.flush();
}
catch (Exception ex)
{
System.err.println("Can't write to log.");
}
System.err.println(msg);
}
public static String doLogin(Socket client, String name)
{
String id;
if (!clients.containsValue(client.getInetAddress()) && !names.containsValue(name) && !ips.containsKey(client.getInetAddress()))
{
do
{
id = makeId();
} while (clients.containsKey(id));
clients.put(id, client);
names.put(id, name);
ips.put(client.getInetAddress(), id);
ids.put(name, id);
System.out.println("Logged in from " + client.getInetAddress() + " with ID " + id);
return "Successfully logged in! Got ID: " + id;
}
else if (names.containsValue(name))
{
return "This user is already online!";
}
else if (ips.containsKey(client.getInetAddress()))
{
return "This IP is already connected!";
}
else
{
return "Login failed. Unkown error!";
}
}
public static void doLogout(InetAddress addr)
{
String clientID = ips.get(addr);
sendMessage(clientID, "Logging you out...");
Socket sock = clients.get(clientID);
clients.remove(clientID);
try
{
sock.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
names.remove(clientID);
ips.remove(addr);
}
private static String makeId()
{
idGenerator = new Random(System.currentTimeMillis() | 5);
String id = String.valueOf(idGenerator.nextInt(9998) + 1);
while (id.length() < 4)
{
String tmp = "0";
id = tmp + id;
}
return id;
}
public static Object[] listClients()
{
return names.keySet().toArray();
}
public static String clientNameByID(String id)
{
return names.get(id);
}
public static String idByName(String name)
{
if (ids.containsKey(name))
{
return ids.get(name);
}
else
{
return "No client with this ID found!";
}
}
public static void sendMessage(String id, String message)
{
try
{
PrintWriter writer = new PrintWriter(clients.get(id).getOutputStream());
writer.println(message);
writer.flush();
writer = null;
}
catch (IOException e)
{
e.printStackTrace();
}
}
public static void broadcastMessage(String message)
{
try
{
for (String client : clients.keySet())
{
PrintWriter writer = new PrintWriter(clients.get(client).getOutputStream());
writer.println(message);
writer.flush();
writer = null;
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
ClientHandler.java
Java:
package de.mrpixeldream.beta.textsender.server.handler;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
import de.mrpixeldream.beta.textsender.server.TextSenderServer;
public class ClientHandler extends Thread
{
Socket client;
String id;
Scanner input;
PrintWriter output;
public ClientHandler(Socket client)
{
this.client = client;
this.id = TextSenderServer.ips.get(client.getInetAddress());
try
{
this.input = new Scanner(client.getInputStream());
this.output = new PrintWriter(client.getOutputStream());
this.output.println("ACK");
this.output.flush();
}
catch (IOException e)
{
e.printStackTrace();
}
}
@Override
public void run()
{
String msg = "";
do
{
msg = "";
try
{
msg = this.input.nextLine();
msg.toUpperCase();
}
catch (Exception e)
{
TextSenderServer.log("Failed to read line from client! Logging out...");
msg = "LOGOUT";
}
if (msg.toUpperCase().startsWith("LOGIN"))
{
this.output.println(TextSenderServer.doLogin(client, msg.split(" ")[1]));
this.output.flush();
}
if (msg.toUpperCase().startsWith("SHOW"))
{
for (Object now : TextSenderServer.listClients())
{
this.output.println(now);
}
this.output.flush();
}
if (msg.toUpperCase().startsWith("SEND"))
{
String id = msg.split(" ")[1];
String send = "";
for (int i = 2; i < msg.split(" ").length; i++)
{
send += msg.split(" ")[i] + " ";
}
try
{
Integer.parseInt(id);
TextSenderServer.sendMessage(id, send);
}
catch (NumberFormatException e)
{
TextSenderServer.sendMessage(TextSenderServer.idByName(id), send);
}
}
if (msg.toUpperCase().startsWith("BROADCAST"))
{
String send = TextSenderServer.clientNameByID(id) + ": ";
for (int i = 1; i < msg.split(" ").length; i++)
{
send += msg.split(" ")[i] + " ";
}
TextSenderServer.broadcastMessage(send);
}
} while (!msg.equalsIgnoreCase("LOGOUT"));
TextSenderServer.doLogout(client.getInetAddress());
}
}
Habe jetzt mal den kompletten Server-Code gepostet, da da (noch) keine großen Geheimnisse drinstecken. Ich hoffe, es ist nicht all zu unübersichtlich.
Sicher sind da noch einige unschöne Sachen wie viel zu viele Statics drin, aber darum soll's jetzt erst einmal nicht gehen, sondern um den oben beschriebenen Semantik-Fehler.
Falls ihr den Server nicht auf dem eigenen Rechner laufen lassen wollt, passt einfach im Client bei der Verbindung das "localhost" auf "dream-code.net" an, dort läuft der Server immer in der aktuellsten Version.
Vielen Dank schon einmal!