为什么此消息被发送到错误的客户端? (重复数据删除)

时间:2014-11-26 22:58:18

标签: java tcp chat server

我有一个聊天程序。问题是我试图禁止欺骗名称。基本上,每当向服务器发送名称更改请求时,都会根据当前正在使用的名称列表进行检查,如果已经采用该名称,则该人员将被添加到我的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();
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

我最终找到了它!

对于遇到类似问题的未来任何人,问题是我在错误的地方分配ip变量!这基本上导致了ip的列表完全相同!另一个错误混淆了这个问题,因为当我在我的shitlist上禁用了消息的发送能力时(不是最好的程序员?),我禁用了所有类型的消息,包括来自服务器的消息等等!糟糕!

上课?臭虫隐藏在最恶劣的地方。走过一切,怀疑你知道的是真实的。什么也不做,验证一切。调试时永远不会有足够的打印语句!

相关问题