2015-07-13 3 views
1

Моя программа в основном:клиент-сервер связи терпит неудачу на Outputstreams

  1. Клиент отправляет строку на сервер,

  2. на основе этой строки, сервер создает ArrayList,

  3. ArrayList отправляется обратно Клиенту.

Что неудачу здесь:

После Клиент посылает строку, сервер принимает его и больше ничего не делать. В это время Клиент продолжает работать и получает NullPointer.

стороне клиента:

public static ArrayList<String> sendStringToServer(String report) { 

    Socket socket; 

    ArrayList<String> fieldsList = new ArrayList<String>(); 

    try { 

     socket = new Socket("localhost", 2345); 

     OutputStream os = socket.getOutputStream(); 
     PrintStream ps = new PrintStream(os, true); 

     ps.println(report); 
     ps.flush(); 

     //Here the debugger should stop and wait for server to create a List 

     //at this point there is no answer, code breaks 
     ObjectInputStream objectInput = new ObjectInputStream(socket.getInputStream()); 

     Object object = objectInput.readObject(); 
     fieldsList = (ArrayList<String>) object; 

     socket.close(); 

     return fieldsList; 

    } catch (IOException e1) { 

     e1.printStackTrace(); 
    } catch (Exception e) { 

     e.printStackTrace(); 
    } 
    return null; 
} 

}

стороне сервера:

public class Server { 

private ServerSocket serverSocket; 
private Socket clientSocket; 
private String telegram; 
private StringBuilder telegramSB; 

public static void main(String[] args) throws IOException, JRException { 

    new Server(); 
} 
public Server() { 

    try { 
     serverSocket = new ServerSocket(2345); 

     while (true) { 

      clientSocket = serverSocket.accept(); 
      InputStream is = clientSocket.getInputStream(); 
      InputStreamReader isr = new InputStreamReader(is); 
      BufferedReader br = new BufferedReader(isr); 

      try { 

       //debugger goes to here and then stops 
       telegram = br.readLine(); 

       int counter = 0; 

       boolean startSeq = false; 

       for (char ch : telegram.toCharArray()) { 

        if (counter == 0 && ch == '/') { 

         startSeq = true; 
        } 

        if (startSeq == true) { 

         telegramSB = new StringBuilder(); 
         telegramSB.append(ch); 
        } 

        if (ch == '\n') { 

         if (telegram.length() < 255) { 

          sendListWithFields(); 

         } else { 

          new Launcher(telegram).run(); 
         } 
        } 
        counter++; 
       } 
      } catch (JRException e) { 

       e.printStackTrace(); 

      } catch (IOException e) { 

       e.printStackTrace(); 

      } 
     } 
    } catch (IOException e) { 

     System.out.println(e); 
    } 
} 
+0

Вы отправляете символ конца строки (EOF)? –

+0

@eyp Да, я делаю, но моя программа так и не дошла. Он считывает буферизованный считыватель и затем останавливается. –

ответ

0

Моя догадка бы, что BufferedReader ждет, чтобы заполнить свой буфер, и вы убежищем 'послал достаточно данных для этого, чтобы сделать это, и вернусь, так что он ждет, пока больше данных не поступит ugh, который никогда не делает (потому что ваши клиенты перестают писать и начинают читать). Вы можете временно протестировать эту теорию, сбросив нагрузку на данные в OutputStream на клиенте и промояв ее.

Если это так, то вы, вероятно, не захотите использовать BufferedReader, но у вас есть другие проблемы, которые также означают, что вы, вероятно, хотите избежать использования PrintStream и BufferedReader для связи и сериализации. Например, кодировка символов по умолчанию на двух разных машинах и JVM может отличаться. Когда вы создаете PrintStream и InputStreamReader, вы не указываете кодировку символов, чтобы они могли не совпадать, и строка, которую вы пишете (включая символ новой строки), может быть полностью понятна удаленной стороне, это также может быть причина его блокировки (клиентская сторона кодирует символ новой строки одним способом, но сервер ожидает, что он будет закодирован совершенно по-другому), хотя, скорее всего, я думаю.

Если вы не имеют использовать PrintStream, то я бы предложил вместо использования DataOutputStream/DataInputStream:

//Client 
BufferedOutputStream bufout = new BufferedOutputStream(socket.getOutputStream()); 
DataOutputStream dout = new DataOutputStream(bufout); 
dout.writeUTF(report); 
dout.flush(); 

//Server 
BufferedInputStream bufin = new BufferedInputStream(socket.getInputStream()); 
DataInputStream din = new DataInputStream(bufin); 
String report = din.readUTF(); 

Вы все еще получаете буферизацию от BufferedIn/OutputStreams так будет производительным, но DataIN/OutputStreams будут управлять завершением объектов переменной длины для вас - они отправят длину, префиксную строку, чтобы указать другой стороне точно, сколько байтов читать, поэтому вам не нужно использовать специальный символ для завершения строки, которую вы написали, и это также означает, что не имеет значения, каково содержание вашей строки. В вашем примере выше, даже если он работал, если у вашей String был символ новой строки, сервер будет читать до первого символа новой строки, а не до конца строки, которую вы отправили, и которая выведет их из синхронизации для следующей отправки/получать по этому потоку.

Использование write/readUTF также определяет кодировку (UTF-8), поэтому там не существует несоответствия.

Смежные вопросы