2012-01-08 2 views
0

Я написал простую программу, в которой сервер должен печатать данные, отправленные несколькими клиентами. Но сервер получает только частичные данные. Ниже приведены соответствующие фрагменты кода.сервер не получает данные от нескольких клиентов (java сокеты)

Сервер:

try { 
     serverSocket = new ServerSocket(8888); 
    } catch (IOException e) { 
     System.err.println("Could not listen on port: 8888"); 
     System.exit(-1); 
    } 
while (listening) { 
    Socket clientSocket = serverSocket.accept(); 
    BufferedReader reader = new BufferedReader(new InputStreamReader(
          clientSocket.getInputStream())); 
     System.out.println(reader.readLine()); 

     reader.close(); 
     clientSocket.close(); 
    } 
    serverSocket.close(); 

Клиент:

try { 
     socket = new Socket("nimbus", 8888); 
     writer = new PrintWriter(socket.getOutputStream(), true); 
     localHost = InetAddress.getLocalHost(); 
    } 
    catch (UnknownHostException e) {} 
    catch (IOException e) {} 

    StringBuilder msg1 = new StringBuilder("A: "); 
    for(int i=1; i<=3; i++) 
     msg1.append(i).append(' '); 
    writer.println(localHost.getHostName() + " - " + msg1); 

    StringBuilder msg2 = new StringBuilder("B: "); 
    for(int i=4; i<=6; i++) 
     msg2.append(i).append(' '); 
    writer.println(localHost.getHostName() + " - " + msg2); 

    StringBuilder msg3 = new StringBuilder("C: "); 
    for(int i=7; i<=9; i++) 
     msg3.append(i).append(' '); 
    writer.println(localHost.getHostName() + " - " + msg3); 

    writer.close(); 
    socket.close(); 

я получаю следующий результат (при запуске на 3-х клиентов)

nimbus2 - A: 1 2 3 
nimbus3 - A: 1 2 3 
nimbus4 - A: 1 2 3 

Я не получаю второе и третье Сообщения. Сервер продолжает ждать. Где я иду не так?

Редактировать: В код сервера я попытался удалить reader.close() и clientSocket.close(). Это тоже не сработало. Другой вопрос - если 3 клиента отправляют 3 сообщения, требуется ли 9 подключений? (по этой причине я закрыл соединение в код сервера)

ответ

1

Возможно, вы захотите делегировать передачу сокета другому потоку. Я написал пример, который работает, передавая каждый входящий сокет Исполнителю, чтобы он мог читать все входы. Я использую Executors.newCachedThreadPool(), который должен расти настолько, насколько это необходимо. Вы также можете использовать Executors.newFixedThreadPool (1), если хотите, чтобы он мог обрабатывать только одного клиента за раз.

Единственное другое изменение, которое я сделал, я удалил BufferedReader и заменил его сканером. У меня возникли проблемы с BufferedReader, которые не возвращают данные. Я не знаю, почему.

Executor exe = Executors.newCachedThreadPool(); 
ServerSocket serverSocket = null; 
try { 
    serverSocket = new ServerSocket(8888); 
} catch (IOException e) { 
    System.err.println("Could not listen on port: 8888"); 
    System.exit(-1); 
} 
while (listening) { 
    final Socket clientSocket = serverSocket.accept(); 

    exe.execute(new Runnable() { 

     @Override 
     public void run() { 
      try { 
       Scanner reader = new Scanner(clientSocket.getInputStream()); 
       while(reader.hasNextLine()){ 
        String line = reader.nextLine(); 
        System.out.println(line); 
       } 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
      try { 
       clientSocket.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    }); 

} 
serverSocket.close(); 
+0

Спасибо. Глядя на ваш код, я понял, что проблема с кодом сервера - это недостающий цикл (для чтения данных). Он отлично работает после добавления цикла (и я использую BufferedReader) – Raghava

+0

Я рад, что смогу помочь. Если вы просто используете цикл, сервер сможет обрабатывать только данные от одного клиента за раз. Если второй клиент подключается, а первый по-прежнему отправляет данные, второй клиент будет вынужден ждать и может истечь. – patheros

+0

ОК, спасибо за ваши входы :). Я бы использовал потоки, как вы предлагали. – Raghava

0

Похоже, вы закрываете соединение с клиентом, прежде чем они смогут закончить запись/до того, как сервер прочитает все отправленные сообщения. Я думаю, вам нужно продолжить до readline и, возможно, не прекратить соединение клиента после отправки вам одного сообщения.

+0

Я попробовал это, и это не сработало ни – Raghava

0

John is right. вы закрываете клиентское соединение, вызывая clientocket.close() после прочтения сообщения, поэтому вы не можете получить другие сообщения. вам следует вызвать clientocket.close(), когда вы получили все сообщения

+0

я попробовал, что я удалил clientSocket.close(), а также reader.close(). Это не работает. Может ли быть другая причина? – Raghava