简体   繁体   中英

Java ServerSocket & Sockets no wait for multi-threaded server

So I have a multithreaded server, and data sends back and forth correctly, but my write operations stalls on the slower connections. I've noticed that it goes by connection time. The first client to connect always receives data first from the server. The next one has to wait until the first one is done receiving and so on so forth. What I'm looking for is a server that sends data to many clients without waiting for a client to finish receiving. I've read up about NIO (non-blocking), but I'd really prefer keeping my current method, which is to use a separate thread for each client.

Here's the code.

Server:

public class Server implements Runnable {

private Thread thread;
private ServerSocket serverSocket;
private ArrayList<ClientThread> clients;

public Server(int port) throws IOException {
    thread = new Thread(this);
    clients = new ArrayList<ClientThread>();
    serverSocket = new ServerSocket(port);
    thread.start();
}

@Override
public void run() {

    while (true) {

        try {
            //Listens to clients connecting.
            ClientThread client = new ClientThread(serverSocket.accept());
            clients.add(client);
            ServerWindow.addText("-- Someone connected!");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

public void broadcast(String data) {
    broadcast(data, null);
}

public void broadcast(String data, ClientThread exclude) {

    int amount = clients.size();

    for (int i = 0; i < amount; i++) {

        if (!clients.get(i).equals(exclude)) { //Don't send it to that client.
            try {
                clients.get(i).broadcast(data);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

}

Client thread object:

public class ClientThread implements Runnable {

private Thread thread;
private Socket socket;
private Scanner input;
private PrintWriter output;

public ClientThread(Socket s) throws IOException {
    thread = new Thread(this);
    socket = s;
    socket.setTcpNoDelay(true);
    //socket.setSoTimeout(10); //Send little chunk for 10 milliseconds.
    input = new Scanner(socket.getInputStream());
    output = new PrintWriter(socket.getOutputStream());
    thread.start();
}

public void run() {

    while (true) {          
        if (input.hasNext()) {
            reciever(input.nextLine());
        }
    }
}

private void reciever(String data) {
    ServerWindow.addText(data);
    ServerWindow.server.broadcast(data, this);
}

public void broadcast(String data) throws IOException {
    output.println(data);
    output.flush();
}

}

It seems you are calling the broadcast method from the same thread.

This is a common pitfall for users new to multithreading in Java.
The fact that the broadcast method is in a subclass of Thread does not mean it will be executed on that Thread

In fact it will be executed on the thread that called it. The only method that will be executed on your created ClientThread is run() and anything that run() calls while it is executing. If you want said thread to not only read data from your connection but also write to it, you have to modify the run method to listen to external commands to start writing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM