Java套接字多次连接尝试 - 无法向所有客户端发送数据

时间:2014-10-25 17:54:00

标签: java sockets console

我在服务器(我自己)和客户端(不同网络中的朋友)之间进行了一对一的套接字聊天工作。现在我尝试做同样的事情,但我尝试创建多个连接,将它们放在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没有收到消息。此外,没有"不正确的命令"服务器控制台上的消息,表示第二个用户的输出不起作用

1 个答案:

答案 0 :(得分:1)

主要问题 - 你有太复杂的线程管理:几个线程试图同时从控制台输入读取:用户1读者线程和用户2读取线程。

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

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