多线程服务器 - 客户端应用程序多次发送响应

时间:2015-11-12 19:51:25

标签: java multithreading hashmap server client

我有一个多线程服务器 - 客户端应用程序。当我尝试在客户端之间进行通信时,我尝试发送的消息被多次发送(例如,当我连接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方法上,但我无法弄清楚

1 个答案:

答案 0 :(得分:0)

这里:

<form id="contact" method="post">
<label for="firstName">First Name:</label><br>
<input type="text" name="firstName" placeholder="First Name" required><br>
<label for="lastName">Last Name:</label><br>
<input type="text" name="lastName" placeholder="Last Name"><br>
<label for="email">Email:</label><br>
<input type="email" name="email" placeholder="Email"><br>
<label for="password">Password:</label><br>
<input type="password" name="password" placeholder="Password"><br>
<input type="button" name="submit" value="Submit">
</form>

您正在向收件人发送与已连接客户端一样多次的邮件。为什么循环?

此外,您还可以在没有同步或锁定的情况下从多个线程读取和写入共享数据,为问题做好准备。