2015-08-31 1 views
3

У меня есть рабочее простое клиент-серверное приложение. Проблема в том, что он отлично работает с одним запущенным клиентом, но не с двумя или более. Он устанавливает соединение, но когда вы пытаетесь ввести текст в первый или второй, сервер бреется. Я думаю, что проблема может быть в функции broadcast() в Server.java.Сервер не работает с несколькими подключениями

Server.java

public class Server { 
    final int PORT = 5000; 
    private ArrayList<NewClient> al = new ArrayList<NewClient>(); 
    private Scanner in; 
    private PrintWriter out; 
    private SimpleDateFormat sdf; 
    private int uniqueID = 0; 

    private void go(){ 

     try{ 
      ServerSocket serverSocket = new ServerSocket(PORT); 
      System.out.println("Waiting for clients..."); 

      while(true) { 
       Socket s = serverSocket.accept(); 
       NewClient chat = new NewClient(s); 
       System.out.println("Client number " + chat.getId() + " connected from: " + s.getLocalAddress().getHostName()); 
       al.add(chat); 
       Thread t = new Thread(chat); 
       t.start(); 

      } 
     }catch (Exception e) { 
      System.out.println("Problem with establishing network connection: "); 
      e.printStackTrace(); 
     } 

    } 

    public static void main(String[] args) { 
     Server server = new Server(); 
     server.go(); 
    } 

    class NewClient implements Runnable{ 
     private Socket socket; 
     private int id; 

     public NewClient(Socket s) { 
      this.socket = s; 
      this.id = ++uniqueID; 
     } 
     public int getId() { 
      return this.id; 
     } 

     @Override 
     public void run() { 
      try{ 
       in = new Scanner(socket.getInputStream()); 
       out = new PrintWriter(socket.getOutputStream()); 
       sdf = new SimpleDateFormat("HH:mm:ss"); 

       while(true) { 
        String input = in.nextLine(); 
        System.out.println("Client said: " + input); 
        broadcast(input); 
       } 
      }catch (Exception e) { 
       e.printStackTrace(); 
      } 

     } 
     private void writeMsg(String input) { 
      String msg = input + " on " + sdf.format(new Date()); 
      out.println("You said: " + msg); 
      out.flush(); 
     } 

     private void broadcast(String input) { 
      for (int i = 0; i < al.size(); i++) { 
       NewClient t = al.get(i); 
       t.writeMsg(input); 
      } 

     } 
    } 

} 

Client.java:

public class Client { 
    final int PORT = 5000; 
    final String HOST = "127.0.0.1"; 
    private Scanner stdIn; 
    private Scanner in; 
    private PrintWriter out; 


    private void go() { 
     setUpNetwork(); 
    } 

    private void setUpNetwork(){ 
     try{ 

      Socket s = new Socket(HOST, PORT); 
      System.out.println("You are connected to " + HOST); 
      NewClient client = new NewClient(s); 
      Thread t = new Thread(client); 
      t.start(); 
     } catch (Exception e) { 
      System.out.println("Problem with connection to server: " + e); 
     } 
    } 
    public static void main(String[] args) { 
     Client client = new Client(); 
     client.go(); 
    } 

    class NewClient implements Runnable { 

     private Socket socket; 
     public NewClient(Socket s) { 
      this.socket = s; 
     } 

     @Override 
     public void run() { 
      try { 
       stdIn = new Scanner(System.in); 
       in = new Scanner(socket.getInputStream()); 
       out = new PrintWriter(socket.getOutputStream()); 

       while(true) { 
        System.out.print("> "); 
        String input = stdIn.nextLine(); 
        out.println(input); 
        out.flush(); 

        if(in.hasNext()) { 
         System.out.println(in.nextLine()); 
        } 
       } 
      }catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

} 

Когда откроется два Client.java и подключить его к server.java все в порядке. Но когда я пытаюсь послать какое-то сообщение с сервера два открытых клиентов возвращает эти ошибки:

java.lang.IndexOutOfBoundsException: end 
    at java.util.regex.Matcher.region(Matcher.java:1038) 
    at java.util.Scanner.findPatternInBuffer(Scanner.java:1010) 
Client said: sds 
    at java.util.Scanner.findWithinHorizon(Scanner.java:1679) 
    at java.util.Scanner.nextLine(Scanner.java:1538) 
    at Server$NewClient.run(Server.java:66) 
    at java.lang.Thread.run(Thread.java:745) 
+0

Не могли бы вы дать более подробную информацию о том, что означает «серверные тормоза»? –

+0

Когда открывается два Client.java и подключается к серверу.java, все в порядке. Но когда я пытаюсь отправить сообщение с этого двух открытых клиентов, сервер возвращает эти ошибки: java.lang.IndexOutOfBoundsException: end \t at java.util.regex.Matcher.region (Matcher.java:1038) \t at java.util .Scanner.findPatternInBuffer (Scanner.java:1010) Клиент сказал: ДСН \t в java.util.Scanner.findWithinHorizon (Scanner.java:1679) \t в java.util.Scanner.nextLine (Scanner.java:1538) \t на сервере $ NewClient.run (Server.java:66) \t at java.lang.Thread.run (Thread.java:745) –

+1

Вы выбрасываете все четные строки ввода клиента, а вы «никогда не проверяйте на конец стрелы м в любом месте. Этого не будет. – EJP

ответ

0

Класс NewClient является внутренним классом. Все экземпляры этого класса создаются с тем же экземпляром внешнего класса. Изменение кода вызовет проблему:

public NewClient(Socket s) { 
      this.socket = s; 
      this.id = ++uniqueID; 
      try{ 
       in = new Scanner(socket.getInputStream()); 
       out = new PrintWriter(socket.getOutputStream()); 
       sdf = new SimpleDateFormat("HH:mm:ss"); 
      }catch(Exception e) { 
       System.out.println("Exception while creating input/output streams: " + e); 
      } 
     } 
0

То, что происходит в том, что ваш код просматривает первую строку от клиента («СДС», которая печатается на стандартный вывод), а затем он возвращается назад и сразу же пытается отсканировать следующую строку от клиента. Поскольку клиент еще ничего не отправил, сканер входного потока выдает исключение.

+0

Я думаю, что проблема в другом месте, потому что это происходит, когда программа входит в широковещательное сообщение и ничего не транслирует. Может ли это быть связано с вашим предложением? –

+0

Трассировка стека говорит, что ошибка возникает в Scanner.nextLine() при вызове из run(), а не из метода broadcast(). Также может быть отдельная ошибка в broadcast(), но это не та, которая бросает эту трассировку стека. –