2012-06-20 2 views
2

Прежде всего, это проблема домашней работы. Говоря, я застрял. Googling для java Properties over Sockets приводит к множеству нерелевантных вещей.Свойства потоковой передачи Java поверх сокета

Я пытаюсь передать объект Properties через сокет. API говорит, что это можно сделать с помощью Stream или Writer/Reader, но я не могу заставить его работать. Я могу сделать это вручную, то есть, если я прочитаю файл строки за строкой и передам его через PrintWriter.

На стороне клиента я получил примерно:

socket = new Socket(host, port); 
outStream = socket.getOutputStream(); 
out = new PrintWriter(outStream, true); 
in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
reader = new BufferedReader(new FileReader(file)); 
... 
props.load(reader); 
props.store(out, null); 

На стороне сервера приемные биты выглядят как:

out = new PrintWriter(sock.getOutputStream(), true); 
inStream = sock.getInputStream(); 
in = new BufferedReader(new InputStreamReader(inStream)); 
... 
props.load(in); // hangs 
// doesn't get to code here... 

В этом случае висит на props.load (в). Вместо того, чтобы делать props.load (in), я читал его в строке за строкой, чтобы убедиться, что работает props.store (out, null), и данные выглядят как переносимые.

Есть что-то о загрузке/хранении Я не понимаю, или это проблема с Stream/Writer/Reader?

+2

Вы закрыли свой выходной разъем после того, как закончили запись свойств на него? –

+1

Вам нужно сообщить серверной стороне сокета, что сообщение завершено. Вам нужен механизм демаркации. Когда заканчивается файл свойств? Сервер не знает, поэтому он пытается продолжать чтение, если вы не закрываете сокет с клиентской стороны или что-то еще не происходит. – mschonaker

+0

Итак, мне нужно закрыть его и снова открыть его? 'Sock.close(); носок.connect(); EDIT: просто прочитайте документы Socket, это не сработает. Если я хочу проверить транзакцию, мне следовало бы это сделать «вручную»? – kjprice

ответ

2

Я думаю, что это будет ответить на этот вопрос, а также How do I recognize EOF in Java Sockets? и What can I send to an InputStream to signify EOF has been reached?

У меня была аналогичная проблема; моя дилемма заключалась в том, что у меня был клиент-серверный запрос-ответ, где один из запросов включал поток, отправленный с клиентской стороны, с использованием clientProps.store(). Соответствующий serverProps.load() на стороне сервера никогда не возвращается, потому что ему нужно увидеть «конец файла» - который в Java означает, что клиент должен закрыть его поток; что приводит к закрытию сокета. Нежелательный результат состоял в том, что я не только не мог оставить ящик открытым для неопределенных обменов запросов и ответов, я даже не мог его открыть, чтобы сервер отправил свой ответ.

Я ненавидел Java заставила меня сделать это, даже больше, потому что документация Properties.load() говорит:

Указанный поток остается открытым после того, как этот метод возвращает.

Этого никогда не случится, если он обнаружит конец файла, увидев поток близко! В любом случае, теперь я все еще люблю Java, потому что это позволило мне использовать это решение (может быть, не полезно, если у вас есть специальная кодировка или локализация данных, которые вы передаете):

Я использовал это на стороне клиента:

PrintWriter toServer; 
    Properties clientProps = new Properties(); 

// ... code to populate the properties and to 
//  construct toServer from the socket ... 

    clientProps.store(toServer, null); 
    toServer.write('\u001A'); // this is an old-school ASCII end-of-file 
    toServer.flush(); 

на стороне сервера я расширенного чтения для обнаружения 1А и возвращают -1 (так что serverProps.load() узнает о конечных из файла в обычном порядке (по видя -1 возвращается из вызова read()) , но ниже, что поток и розетка остаются открытыми.

BufferedReader fromClient; 
    Properties serverProps = new Properties(); 


// ... code to construct fromClient from the socket ... 

    serverProps.load (new PropReader (fromClient)); 

///// 

    private static class PropReader extends Reader { 

    BufferedReader src; 
    boolean eof=false; 

    private PropReader(BufferedReader fromClient) { 
     super(); 
     src=fromClient; 
    } 


    @Override 
    public int read(char[] cbuf, int off, int len) throws IOException { 
     int inCount; 

     if (!eof) { 
      inCount = src.read(cbuf, off, len); 

      if (inCount > 0) { 
       // we read a buffer... look at the end for the EOF that the client used to mark the end of file 
       if (cbuf[off+inCount-1] == '\u001A') { 
        --inCount; // don't send eof with the data 
        eof = true; // next time... we'll return -1 
       } 
      } 
     } else { 
      inCount = -1; 
     } 

     return inCount; 
    } 

    @Override 
    public void close() throws IOException { 
     src.close(); 
    } 
+0

С момента написания этого я добавил это после 'toServer.flush()' на стороне клиента: 'synchronized (props) {try {props.wait (10); } catch (InterruptedException ex) {}} '... похоже, что клиент отправил свой следующий запрос так быстро, что он был буферизирован на стороне сервера и попал в перекрывающееся чтение. Результат состоял в том, что ** eof ** был _not_ последним символом в буффевере на стороне сервера. – PMorganCA

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