Как отправить сообщение через несколько потоков в Java? - PullRequest
2 голосов
/ 18 марта 2011

Я сделал простой чат-сервер и клиент, и клиент отправит текст на сервер, а сервер отправит его обратно только клиенту, который его отправил.Я хочу, чтобы он отправлял всем клиентам, а не только этому.

Сервер:

import java.io.IOException;
import java.net.ServerSocket;

public class Server {

    public static void main(String[] args) throws IOException {
        ServerSocket s = null;
        boolean listening = true;
        try {
            s = new ServerSocket(5555);
        } catch (IOException e) {
            e.printStackTrace();
        }

        while(listening)
            new ServerThread(s.accept()).start();

    }

}

Тема:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class ServerThread extends Thread {

    private Socket sock = null;

    public ServerThread(Socket socket) {
        super("Server Thread.");
        this.sock = socket;
    }

    public void run() {

        PrintWriter out = null;
        BufferedReader in = null;

        try {
            System.out.println(sock.getInetAddress() + " has joined.");
            out = new PrintWriter(sock.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(sock.getInputStream()));

            String input;

            while((input = in.readLine()) != null) {
                System.out.println(input);
                out.println(input);
            }

            in.close();
            out.close();
            sock.close();

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

Клиент:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client 
{
    public static void main(String[] args) throws IOException {
        Socket sock = null;
        PrintWriter out = null;
        BufferedReader in = null;

        try {
            sock = new Socket("127.0.0.1", 5555);
            out = new PrintWriter(sock.getOutputStream(), true);
            in = new BufferedReader(
                    new InputStreamReader(sock.getInputStream()));
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        BufferedReader stdIn = new BufferedReader(new InputStreamReader(
                System.in));
        String userInput;


        while ((userInput = stdIn.readLine()) != null) {    
            out.println(userInput);
            System.out.println(in.readLine());
        }

        out.close();
        in.close();
        sock.close();
    }

}

Ответы [ 4 ]

1 голос
/ 18 марта 2011
Световой кодер

и Эрнест Фридман-Хилл, похоже, дают хороший совет, но я хотел бы добавить одну вещь: вы рассматривали возможность использования шаблона Observer и реализации по умолчанию java Observable ?

Сервер может расширять объект Observable, а ServerThread может реализовывать интерфейс Observer.При создании новых ServerThreads зарегистрируйте их в Observable, используя

server.addObserver(serverThread);

. ServerThread необходимо будет знать о сервере, с которым он связан.Затем всякий раз, когда клиент отправляет новое сообщение вместо out.println (userInput), выполните следующее:

synchronized (server) {
    server.setChanged();
    server.notifyObservers(userInput);
}

Вам также необходимо реализовать ServerThread.update (Observable o, Object update), в котором выполучит выходной поток сокета serverThread и запишет в него ((String) update).

Обратите внимание, что при этом будет использоваться один поток для отправки сообщений всем наблюдателям, и другие потоки будут блокировать обработку своих чатов, пока он не получитотправлено всем наблюдателям.

1 голос
/ 18 марта 2011

Ну, вкратце: вы создаете эти ServerThreads и запускаете их, но вы никоим образом не отслеживаете их. Представьте, что каждый раз, когда вы его создаете, вы помещаете его в HashSet. Затем каждый раз, когда клиент отправлял строку, вы перебирали набор и отправляли строку каждому из клиентов. Конечно, метод sendMessage (String) в ServerThread упростит эту задачу.

1 голос
/ 18 марта 2011
  1. Измените в своем клиенте один поток для чтения с сервера и один поток для чтения с клавиатуры.

  2. Создайте функцию, которая разрешает потоки сокетов серверасвязываться друг с другом и использовать синхронизацию, чтобы в каждый выходной поток одновременно записывался только один поток.Итак, вкратце, создайте список потоков сервера, который является общим для всех потоков, и переместите ваш PrintWriter в поле с геттером, чтобы к нему можно было получить доступ извне.

1 голос
/ 18 марта 2011

Ваш сервер должен сохранять List<ServerThread>Server есть метод void sendAll(String), к которому может обращаться ServerThreads, и когда они получают информацию, этот sendAll() метод сообщает каждому ServerThread, чтобы он отправил свою информацию.

Что высмотря на выполнение, хотя потребуется некоторая асинхронная работа (и, безусловно, не тривиальная!)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...