【问题标题】:Why is this message getting sent to the wrong client? (Deduping)为什么此消息被发送到错误的客户端? (重复数据删除)
【发布时间】: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();
            }
        }
    }
}

【问题讨论】:

  • 废话,添加了旧版本的源代码,现在修复!
  • 已修复!我认为这是现在正确的代码。我一直在搞砸它试图修复它。

标签: java tcp chat server


【解决方案1】:

我终于找到了!

对于以后遇到类似问题的人来说,问题是我在错误的地方分配了ip 变量!这基本上导致了ip列表都是一样的!另一个错误混淆了这个问题,因为当我在shitlist 上禁用消息发送功能时(程序员不是最讨厌的吗?),我禁用了所有类型的消息,包括来自服务器的消息等!糟糕!

教训?虫子藏在最肮脏的地方。遍历所有内容,并怀疑您所知道的是真实的。什么都不做,验证一切。调试时打印语句永远不够!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-08
    • 2020-12-28
    • 2019-01-26
    • 2021-10-08
    • 2020-12-17
    • 1970-01-01
    • 2021-08-19
    • 2013-04-24
    相关资源
    最近更新 更多