【问题标题】:Java Sockets multiple connection attempt - Can't send data to all clientsJava Sockets 多次连接尝试 - 无法向所有客户端发送数据
【发布时间】:2014-10-25 17:53:59
【问题描述】:

我在服务器(我自己)和客户端(不同网络中的朋友)之间进行了一对一的套接字聊天。现在我正在尝试做同样的事情,但我正在尝试创建多个连接,将它们放在Executors.newFixedThreadPool(poolSize) 中,其中部分代码取自ExecutorService 文档。

服务器正常工作并接受连接,但是,当我尝试建立第二个连接并向其发送消息时出现问题。虽然每个客户端都可以向服务器发送消息,但服务器只能向第一个客户端发送消息。

这里是完整的代码:

public class MultipleServer implements Runnable {

  private final ServerSocket serverSocket;
  private final ExecutorService pool;
  Scanner console;

  public MultipleServer(int port, int poolSize, Scanner mainconsole)
      throws IOException {
    serverSocket = new ServerSocket(port);
    pool = Executors.newFixedThreadPool(poolSize);
    console = mainconsole;
  }

  public void run() {
    try {
      for(;;) {
        pool.execute(new Handler(serverSocket.accept(), console));
      }
    } catch (IOException ex) {
      pool.shutdown();
    }
  }
}
class Handler implements Runnable {

  private Socket socket;
  private Scanner console;
  private String name = "undefined";

  Handler(Socket socket, Scanner console)
  {
    this.socket = socket;
    this.console = console;
  }

  public void run()
  {
    if (socket.isConnected())
    {
      System.out.println("connection from " + socket.getLocalAddress().getHostAddress());

      Thread inputthread = new Thread(new Runnable()
      {

        @Override
        public void run()
        {
          PrintWriter out;
          try
          {
            out = new PrintWriter(socket.getOutputStream(), true);
            out.println("Welcome to my server. Input your name");
            out.flush();
            String line;
            while ((line = console.nextLine()) != null)
            {
              if (line.contains("/"))
              {
                if (line.equals("/q " + name))
                {
                  out.println("Connection closing");
                  System.out.println("Connection to " + name + "closing");
                  out.close();
                  socket.close();

                } else if (line.substring(0, name.length() + 3).equals("/m " + name))
                {
                  out.println(line.substring(name.length() + 4));
                  out.flush();
                }
              } else
              {
                System.out.println("Incorrect command");
              }
            }
            if (socket.isClosed())
            {
              out.close();
            }
          } catch (IOException e)
          {
            e.printStackTrace();
          }
        }
      });

      Thread outputthread = new Thread(new Runnable()
      {
        int msgno = 0;

        @Override
        public void run()
        {
          BufferedReader in;
          try
          {
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            while (!socket.isClosed())
            {
              while (!in.ready())
              {
                Thread.sleep(100);
              }
              String msg = in.readLine();
              if (msgno == 0)
              {
                name = msg;
                msgno++;
              } else
              {
                System.out.println(name + ": " + msg);
              }
              synchronized (this)
              {
                this.wait(100);
              }
            }
            if (socket.isClosed())
            {
              in.close();
            }
          } catch (IOException e)
          {
            e.printStackTrace();
          } catch (InterruptedException e)
          {
            e.printStackTrace();
          }
        }
      });
      inputthread.start();
      outputthread.start();
    }
  }

  public static void main(String[] args) throws IOException
  {
    int connections = 10;
    int port = 80;
    Scanner scanner = new Scanner(System.in);
    MultipleServer server = new MultipleServer(port, connections, scanner);
    server.run();

  }
}

更具体地说,抛出的异常:

Exception in thread "Thread-2" java.lang.IndexOutOfBoundsException: end
    at java.util.regex.Matcher.region(Unknown Source)
    at java.util.Scanner.findPatternInBuffer(Unknown Source)
    at java.util.Scanner.findWithinHorizon(Unknown Source)
    at java.util.Scanner.nextLine(Unknown Source)
    at Handler$1.run(MultipleServer.java:61)
    at java.lang.Thread.run(Unknown Source)

有问题的行在哪里:

while((line=console.nextLine())!=null){

澄清:当第二个用户加入服务器时会发生此异常。当我键入 /m user1 消息时,第一个用户会收到预期的消息,当我键入 /m user2 消息时,没有错误,但 user2 没有收到消息。此外,服务器控制台上没有“错误命令”消息,这意味着第二个用户的输出不起作用

【问题讨论】:

  • 您在异常跟踪中缺少一些行。请粘贴整个跟踪。
  • 这是控制台中出现的全部异常
  • 所有行都缺少一些字符。例如,java.lang.IndexOut 应该是 java.lang.IndexOutOfBoundException
  • 你是对的,对不起。编辑它。

标签: java sockets console


【解决方案1】:

主要问题 - 您的线程管理过于复杂:多个线程尝试同时从控制台输入读取:用户 1 读取线程和用户 2 读取线程。

您应该引入一个单独的路由器线程,负责与管理员通信并通过共享并发结构管理衍生线程之间的所有消息。

对于此类任务,最好使用任何现有的框架,例如nettynirvana messaging

【讨论】:

  • 当然它会让生活变得更简单,但我正在努力了解这一切是如何运作的。您能否详细说明我如何制作单个路由器线程?允许我仅输出到套接字的选定输出流的东西。
  • 1.您应该描述一个消息结构(作者、文本、收件人/组/全部)。 2. 在每个阅读器线程中,您应该将传入消息包装到此结构中并传递到共享(!)路由器队列中。 3. 路由器线程应该处理所有传入的消息并将它们翻译给所有的作者。 4. 单独的管理员线程应该与控制台通信并将特殊消息发送到路由器,可能通过单独的队列。
猜你喜欢
  • 1970-01-01
  • 2015-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-25
  • 2019-08-04
相关资源
最近更新 更多