我有一个多线程服务器-客户端应用程序。当我尝试在客户端之间进行通信时,我尝试发送的消息会发送多次(例如,当我连接2-3个客户端时,该消息发送2次,当我连接10个客户端时,该消息发送6次)。这是代码:

ServerProtocol类:

public class ServerProtocol {

    private String nick;
    private final ClientConn conn;

    private static final HashMap < String, ClientConn > nicks = new HashMap < > ();
    private static final String msg_WELCOME = "You are connected to server";
    private static final String msg_OK = "Message sent";
    private static final String msg_NICK_IN_USE = "Nick in use";

    private static final String msg_SEND_FAILED = "Failed to send";

    public ServerProtocol(ClientConn c) {
        nick = null;
        conn = c;
    }

    private byte[] authenticate(String mesaj) {

        String id = mesaj.substring(0, 1);

        if (!nicks.containsKey(id)) {
            nicks.put(id, this.conn);
            System.out.println(id + " joined.");
            this.nick = id;

            return msg_WELCOME.getBytes();

        } else {
            return msg_NICK_IN_USE.getBytes();
        }

    }

    public boolean sendMsgCSP(String recipient, String msg) throws IOException {
        if (nicks.containsKey(recipient)) {
            int e = nicks.size();
            for (int i = 0; i < e; i++) {
                ClientConn c = nicks.get(recipient);
                //c.sendMsgCC(nick.getBytes());
                c.sendMsgCC(msg.getBytes());
                System.out.println("message sent: " + msg + " to client " + recipient);
            }
            return true;
        } else {
            return false;
        }
    }

    public byte[] process(byte[] msg) throws IOException {
        //System.out.println(Arrays.toString(msg));
        String mesaj = new String(msg);
        if (!nicks.containsKey(nick)) {
            return authenticate(mesaj);
        }

        System.out.println("message:" + mesaj);

        if (sendMsgCSP(mesaj.substring(0, 1), mesaj.substring(1))) {
            return msg_OK.getBytes();
        } else {
            return msg_SEND_FAILED.getBytes();
        }
    }
}


ClientConn类:

public class ClientConn implements Runnable {

    private final Socket clients;
    private OutputStream os;
    private DataOutputStream dos;
    private InputStream is;
    private DataInputStream dis;

    ClientConn(Socket client) {
        this.clients = client;

        try {
            is = clients.getInputStream();
            dis = new DataInputStream(is);
            os = clients.getOutputStream();
            dos = new DataOutputStream(os);

        } catch (IOException ex) {
            Logger.getLogger(ClientConn.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    @Override
    public void run() {

        byte[] read, response;
        ServerProtocol protocol = new ServerProtocol(this);

        try {

            while (true) {
                read = readBytes();

                //System.out.println(Arrays.toString(rd));
                //System.out.println("message received: " + Arrays.toString(read));
                response = protocol.process(read);

                sendMsgCC(response);


            }
        } catch (IOException ex) {
            System.out.println(ex);

        }
    }

    public void sendMsgCC(byte[] myByteArray) throws IOException {
        int start = 0;
        int len = myByteArray.length;
        if (len < 0) {
            throw new IllegalArgumentException("Negative length not allowed");
        }
        if (start < 0 || start >= myByteArray.length) {
            throw new IndexOutOfBoundsException("Out of bounds: " + start);
        }

        dos.writeInt(len);
        if (len > 0) {
            dos.write(myByteArray, start, len);

        }
    }

    public byte[] readBytes() throws IOException {
        int len = dis.readInt();
        byte[] data = new byte[len];

        if (len > 0) {
            dis.readFully(data);
        }

        return data;

    }

}


我认为问题出在sendMsgCC方法上,但我无法弄清楚

最佳答案

这里:

   for (int i = 0; i < e; i++) {
        ClientConn c = nicks.get(recipient);
        c.sendMsgCC(msg.getBytes());
        System.out.println("message sent: " + msg + " to client " + recipient);
    }


您发送邮件给收件人的次数与已连接客户端的次数相同。为什么循环?

另外,您还可以从多个线程读取和写入共享数据,而无需同步或锁定,因此可以为问题做准备。

10-01 22:16