【发布时间】:2015-01-25 10:35:16
【问题描述】:
我有一个聊天程序。问题是我试图禁止欺骗名称。本质上,每当向服务器发送名称更改请求时,都会根据当前使用的名称列表检查它,如果已经使用,则将该人添加到我的shitlist(不允许发布)并发送他们需要更改姓名的消息。
我把代码中的废话注释掉了,因为有很多所以你可以很容易地理解它。
问题是错误的人被发送了该名称已被使用的消息!在过去的 8 个小时里,我一直在努力寻找它,这真让我发疯!
服务器端代码较长;我将发布相关位,并将根据要求提供任何进一步的信息。我还将链接到完整的程序。 (不是来源,JAR。)
JAR:https://www.mediafire.com/?4t2shjdjf7blpg2
//...Irrelevant bits ommitted...//
public class Server
{
// The server object reference
static Server server;
// Declarations:
private ArrayList<ObjectOutputStream> clientOutputStreams; // out streams
private ArrayList<String> takenNames = new ArrayList<>(); // taken names
private InetAddress ip;
private final int serverPort; // the port the server is running on
private static ObjectOutputStream changer; // the last person to change names
private ArrayList<ObjectOutputStream> shitList = new ArrayList<>();
private HashMap <InetAddress, ObjectOutputStream> ipMap =
new HashMap<>(); // <ip, outputstream>
//...Irrelevant bits ommited...//
// Don't mind this non-indentation, it is supposed to be.
public void tellEveryone(Message message, InetAddress senderIP)
{
// First check some special conditions..
if(message.getType() == Message.TYPE.IN_USE)
{
try
{
changer.writeObject(message);
}
catch (IOException e)
{
e.printStackTrace();
}
}
// If someone is on my shitlist,
if(shitList.contains(ipMap.get(senderIP)))
{
// Warn them of their sins...
Message nopeMessage = new Message(Message.TYPE.SERVER,
"You may not send any messages until you change your name!",
"Server");
try
{
ipMap.get(senderIP).writeObject(nopeMessage);
}
catch(IOException e)
{
e.printStackTrace();
}
}
else
{
// Send message normally to everyone...
// Sync, just to be safe
synchronized(clientOutputStreams)
{
for(ObjectOutputStream oo : clientOutputStreams) // while more clients...
{
try
{
oo.writeObject(message);
oo.flush();
}
catch(IOException e)
{
System.out.println("IOException caught during tellEveryone()");
e.printStackTrace();
}
}
}
System.out.println(getTimeStamp() + ": Message Sent by:".
concat(" " + senderIP + "/ " + message.getSenderName()));
}
}
服务器处理程序内部类...
public class ServerHandler implements Runnable
{
@Override
public void run()
{
// Create a list of client out streams to send stuff...
clientOutputStreams = new ArrayList<>();
try // To establish a connection with clients
{
// Create server socket...
ServerSocket serverSocket = new ServerSocket(serverPort);
while(true) // Will always run! Blocks!
{
// Assign a client socket to any new socket connections...
// (The var used here is temp, but will be passed off soon.)
Socket clientSocket = serverSocket.accept();
// Get's the ip of the client that connected...
ip = clientSocket.getInetAddress();
System.out.println(ip + " " + "connected.");
// Create ooStream to send messages to client...
ObjectOutputStream ooStream =
new ObjectOutputStream(
clientSocket.getOutputStream());
// Add the client oo stream to the list of outputs...
clientOutputStreams.add(ooStream);
// Add user IP data to map of ip's
ipMap.putIfAbsent(ip, ooStream);
// Create new thread to run inner class ClientHandler...
Thread t = new Thread(new ClientHandler(clientSocket));
// Running the thread makes it safe to overwrite the...
// ...clientsocket variable.
t.start();
}
}
catch (IOException e)
{
System.out.println("Exception in server.run()");
// TODO: Revise
e.printStackTrace();
}
}
}
客户端处理程序内部类
public class ClientHandler implements Runnable
{
private ObjectInputStream oInStream; // The client's input stream.
private Socket socket; // Socket to the client
public ClientHandler(Socket clientSocket)
{
try // to create an input stream...
{
socket = clientSocket; // <-- The one passed in to the method
// Potential error from previous version... REMOVE WHEN TESTED
oInStream = new ObjectInputStream(socket.getInputStream());
}
catch(IOException e)
{
System.out.println("Error establishing input stream");
}
}
@Override
public void run()
{
Message message;
try // To process incoming messages...
{
while(socket.isClosed() == false) // If the socket is open...
{
// While there are more messages...
// Also assigns to the message var.
while((message = (Message)oInStream.readObject()) != null)
{
// Passes on the message and sender info.
if(message.getType() == Message.TYPE.NAME_REQUEST)
{
changer = ipMap.get(socket.getInetAddress());
System.out.println(socket.getInetAddress());
System.out.println(changer.toString());
handleNameRequests(message);
}
else
{
tellEveryone(message, ip); // TEST CHANGE- DELETED IF TEST
}
}
// TEST TEST TEST
synchronized(clientOutputStreams)
{
int index =
clientOutputStreams.indexOf(
socket.getOutputStream());
clientOutputStreams.remove(index);
System.out.println("Removed the client in sync");
}
}
// TEST TEST TEST
socket.close(); // TEST CLOSING SOCKET WHEN DONE.
System.out.println("Sock closed after while loop in ch run()");
}
catch(IOException e)
{
System.out.println("IOException caught when "
+ "reading message.");
}
catch (ClassNotFoundException e)
{
System.out.println("Some poor sap is going to have to debug"
+ "this!");
}
finally
{
// THIS WHOLE BLOCK: TEST TEST TEST
try
{
oInStream.close();
System.out.println("just closed oinStream");
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
}
【问题讨论】:
-
废话,添加了旧版本的源代码,现在修复!
-
已修复!我认为这是现在正确的代码。我一直在搞砸它试图修复它。