【问题标题】:Listen to multiple InputStreams?听多个 InputStreams?
【发布时间】:2012-10-09 07:52:29
【问题描述】:

我正在使用像 MSN 这样的 IM 程序用 Java 制作一个聊天程序。现在,我的程序不会像 MSN 那样功能齐全,我也不会深入研究广泛的 GUI 设计。

我的问题是,我可能会选择错误的设计来做到这一点。

我目前正在设计一个会话对象。基本上,用户与服务器联系并处于“边缘”状态,直到他们决定邀请某人聊天。然后是服务器的工作(还没有到那部分)在所涉及的用户之间建立一个会话。

我的问题是,我必须监听多个 InputStream 的变化并相应地更新每个人的显示。当其中一个“向会话发送消息”时,我将如何设法监听所有 InputStream 并进行更新?

到目前为止,这是我的代码。时间不长。

包服务器;

import java.io.*;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
 *
 * @author Vipar
 */
public class Session implements Runnable {
    private static User[] users;
    private static PrintWriter[] outputs;
    private int sessionId;

    public Session(User[] users) {
        this.users = users;
        outputs = new PrintWriter[users.length];
        sessionId = this.hashCode();

        try {
            for(int i = 0; i < users.length; i++) {
            outputs[i] = new PrintWriter(users[i].getSocket().getOutputStream(), true);
            }
        } catch (IOException ioe) {
            ChatServer.print("An error occured in session " + sessionId);
            ChatServer.print(ioe.getMessage());
        }
    }

    @Override
    public void run() {
        ChatServer.print("SessionId: " + sessionId + " have initiated.");
        ExecutorService service = Executors.newFixedThreadPool(users.length);
        for(int i = 0; i < users.length; i++) {
            service.submit(new InputStreamListener(users[i]));
        }
        do {
            if(users.length < 2) {
                ChatServer.print("SessionId: " + sessionId + " have ended.");
                break;
            }
        } while(true);
    }

    public static void update(User u, String message) {
        for(int i = 0; i < users.length; i++) {
            outputs[i].println("new");
            outputs[i].println(u.getUserName());
            outputs[i].println(message);
        }
    }
}

我刚刚做的InputStreamListener:

package server;

import java.util.Scanner;
import java.io.*;
import java.util.NoSuchElementException;

/**
 *
 * @author Vipar
 */
public class InputStreamListener implements Runnable {
    private Scanner scanner;
    private User user;
    public InputStreamListener(User user) {
        this.user = user;
        try {
            scanner = new Scanner(user.getSocket().getInputStream());
        } catch (IOException ioe) {
            ChatServer.print("An Error occured for the InputStream: "
                    + user.getUserName());
            ChatServer.print(ioe.getMessage());
        }

    }

    @Override
    public void run() {
        String s = "";
        do {
            try {
                s = scanner.nextLine();
                Session.update(user, s);
            } catch(NoSuchElementException e) {
                continue;
            }
        } while(!s.equals("/DISCONNECT"));
        try {
            user.getSocket().close();
        } catch(IOException ioe) {
            ChatServer.print("Problem closing users InputStream: "
                    + user.getUserName());
            ChatServer.print(ioe.getMessage());
        }
    }
}

【问题讨论】:

  • 我会为每个连接使用一个线程,并使用 ExecutorService 来保存所有线程,以便它们被回收。
  • 服务器应该管理线程部分。这样每个会话都有自己的线程来运行。
  • 我相信是最简单的,。您可以避免使用非阻塞 NIO 执行此操作,但这会增加很多复杂性,除非您知道自己需要它,否则我会避免这样做。
  • 在考虑 NIO 或 NIO2 之前,我会先让 IO 实现工作;)

标签: java io inputstream


【解决方案1】:

最简单的方法是为每个客户端使用一个线程。每个线程都从自己的 InputStream 中读取数据并通知会话有关新消息的信息。这样的线程也可以知道如何将消息发送回客户端。 如果您希望有很多客户端,您可以尝试一些比线程更轻量级的东西,比如演员(例如Akka)。或者尝试在 NIO 中使用异步 IO。

【讨论】:

  • 我尝试使用 ExecutorService 更新代码。但我不确定我是否做得正确。
  • 那么让update()方法同步,让该方法不发送给发送消息的用户?你还有什么注意的吗?恐怕这会炸毁xD
  • 现在您可以将synchronized 添加到update 方法,但这不是生产解决方案。您将会话数据存储在静态变量中(为什么?),因此每条消息都会阻止其他消息,它们将被一一发送。
  • 我将创建类 Client,它将知道如何与客户端(IN 和 OUT)进行通信。每个客户端与Session通信,Session向其他客户端重新发送消息。
  • 静态变量是因为我在静态方法中使用它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-28
  • 2011-01-10
  • 2015-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多