Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 向特定的客户端线程发送消息_Java_Sockets_Server - Fatal编程技术网

Java 向特定的客户端线程发送消息

Java 向特定的客户端线程发送消息,java,sockets,server,Java,Sockets,Server,我有一个服务器类 import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; public class Server { public static ArrayList<String> waiting = new ArrayList<String>(); public static ArrayList<String> playing = n

我有一个服务器类

import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class Server {
    public static ArrayList<String> waiting = new ArrayList<String>();
    public static ArrayList<String> playing = new ArrayList<String>();
    public static ArrayList<Integer> score = new ArrayList<Integer>();

    public static void main(String[] args) {
        try {
            ServerSocket server = new ServerSocket(4321);
            while (true) {
                try {
                    Socket socket = server.accept();
                    new EchoThread(socket).start();
                } catch (Exception exc) {
                    exc.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void addClient(String name) {
        waiting.add(name);
    }

    public int getNumClients() {
        return waiting.size();
    }

    public String getClientName(int i) {
        return waiting.get(i);
    }

    public void play() {
        int scr = 0;
        for (int i = 0; i < 4; i++) {
            playing.add(waiting.get(0));
            score.add(scr);
            waiting.remove(0);
        }
    }

    public boolean checkIfPlaying(String name) {
        if (playing.indexOf(name) >= 0) {
            return true;
        } else {
            return false;
        }
    }
}
如果客户端连接到服务器,则客户端的名称存储在服务器类数组中,等待。 如果等待的客户端等于4,它将从等待阵列中移除并将其放入播放阵列中

我想让服务器向播放阵列中的前4个客户端发送消息


我该怎么做呢?

对于您的服务器类,我会将您的ArrayList更改为等待并播放到ArrayList。这样,服务器类就可以跟踪每个客户机对象本身,而不仅仅是它们的名称。当您实例化EchoThread对象时,我会将本地服务器对象传递给每个EchoThread,这样每个对象都知道实例化它们的服务器

服务器类

import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class Server {
    public ArrayList<EchoThread> waiting = new ArrayList<EchoThread>();
    public ArrayList<EchoThread> playing = new ArrayList<EchoThread>();
    public ArrayList<Integer> score = new ArrayList<Integer>();

    public static void main(String[] args) {
        try {
            // Instantiate a single server object that you can pass into your connected clients
            Server myServer = new Server();
            ServerSocket server = new ServerSocket(4321);
            while (true) {
                try {
                    Socket socket = server.accept();
                    // Pass myServer into Echo Thread 
                    new EchoThread(myServer, socket).start();
                } catch (Exception exc) {
                    exc.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // Have to synchronize this since multiple clients could be adding to this list at the same time
    public synchronized void addClient(EchoThread client) {
        waiting.add(client);
    }

    public int getNumClients() {
        return waiting.size();
    }

    public String getClientName(int i) {
        return waiting.get(i).getCName();
    }

    public void play() {
        int scr = 0;
        for (int i = 0; i < 4; i++) {
            EchoThread clientBeingMovedToPlaying = waiting.get(0);
            playing.add(clientBeingMovedToPlaying);
            score.add(scr);
            waiting.remove(0);

            // This will be a new method in your EchoThread class
            clientBeingMovedToPlaying.SendServerPlayingMessage();
        }
    }

    public boolean checkIfPlaying(String name) {
        boolean isPlaying = false;
        for(EchoThread client : playing) {
            if (client.getName().contentEquals(name)) {
                isPlaying = true;
                break;
            }
        }
        return isPlaying;
    }
}

我想这会让你得到你想要的。。。请原谅任何语法或逻辑错误,目前我面前没有IDE。

您正在存储等待的客户端的IP/端口吗?@Ziad,不,我需要存储它吗?有一个错误,发送EchoThread,如何将其作为参数发送?EchoThread本身?在EchoThread类中,我做了一些编辑。我添加了一个clientName作为字符串,这样您仍然可以将客户端的名称作为对象的一部分。然后在调用s.addClient()时,只需传递this关键字。非静态变量这不能从静态上下文引用哦,天哪!我的道歉。。。您必须在main中创建类的本地对象,因为main是一个静态方法。我已经对我的答案做了必要的修改。getName呢?我想你没有设置线程的名称?
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class Server {
    public ArrayList<EchoThread> waiting = new ArrayList<EchoThread>();
    public ArrayList<EchoThread> playing = new ArrayList<EchoThread>();
    public ArrayList<Integer> score = new ArrayList<Integer>();

    public static void main(String[] args) {
        try {
            // Instantiate a single server object that you can pass into your connected clients
            Server myServer = new Server();
            ServerSocket server = new ServerSocket(4321);
            while (true) {
                try {
                    Socket socket = server.accept();
                    // Pass myServer into Echo Thread 
                    new EchoThread(myServer, socket).start();
                } catch (Exception exc) {
                    exc.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // Have to synchronize this since multiple clients could be adding to this list at the same time
    public synchronized void addClient(EchoThread client) {
        waiting.add(client);
    }

    public int getNumClients() {
        return waiting.size();
    }

    public String getClientName(int i) {
        return waiting.get(i).getCName();
    }

    public void play() {
        int scr = 0;
        for (int i = 0; i < 4; i++) {
            EchoThread clientBeingMovedToPlaying = waiting.get(0);
            playing.add(clientBeingMovedToPlaying);
            score.add(scr);
            waiting.remove(0);

            // This will be a new method in your EchoThread class
            clientBeingMovedToPlaying.SendServerPlayingMessage();
        }
    }

    public boolean checkIfPlaying(String name) {
        boolean isPlaying = false;
        for(EchoThread client : playing) {
            if (client.getName().contentEquals(name)) {
                isPlaying = true;
                break;
            }
        }
        return isPlaying;
    }
}
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

public class EchoThread extends Thread {
    protected Socket socket;
    protected Server s;
    protected DataInputStream in;
    protected DataOutputStream out;
    protected String line;
    protected String clientName;

    // This way, each EchoThread object knows about the server
    public EchoThread(Server theServer, Socket clientSocket) {
        this.s = theServer;
        this.socket = clientSocket;
    }

    public void run() {
        try {
            in = new DataInputStream(socket.getInputStream());
            out = new DataOutputStream(socket.getOutputStream());
        } catch (IOException e) {
            return;
        }

        while (true) {
            try {
                line = in.readLine();
                String[] prot = line.split(":");

                if (prot[0].equals("/login")) {
                    // Original code
                    //s.addClient(prot[1]);

                    // New code
                    clientName = prot[1];
                    s.addClient(this);
                } else if (prot[0].equals("/waiting")) {
                    if (s.checkIfPlaying(prot[1])) {
                        out.writeBytes("Playing" + "\r\n");
                    } else {
                        // You don't want multiple clients firing the play method, so you need to synchronize your server object
                        synchronized (s) {
                            if (s.getNumClients() >= 4) {
                                s.play();
                                out.writeBytes("Playing" + "\r\n");
                            } else {
                                out.writeBytes(s.getNumClients() + "\r\n");
                            }
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }
        }
    }

    public String getCName() {
        return clientName;
    }

    public void SendServerPlayingMessage() {
        if (out != null) {
            // Send whatever message you want
        }
    }
}