2013-12-18 5 views
3

У меня есть простой сервер C и Java-клиент. Я отправляю текстовый файл построчно от сервера к клиенту:Как определить конец чтения

do { 
     send(sockfd, line, strlen(line), 0); 
     printf("%s\n", line); 
    } while ((fgets(line, 100, fp)) != NULL); 

и читать его в Java клиента с:

Client.getCl().getInputStream().read(inmsg); 
    do{    
     decoded = new String(inmsg, "UTF-8"); 
     System.out.println(decoded); 
    }while(Client.getCl().getInputStream().read(inmsg) > 0); 

Моя проблема заключается в том, что я не знаю, как отправить «конец чтения "от сервера к клиенту. Клиент замораживается при последнем чтении. Я знаю, что метод read() возвращает целое число с числом получающих байтов и -1, когда читать нечего и 0, когда длина буфера равна нулю. Единственное решение, которое возвращало -1 клиенту, заключалось в том, чтобы закрыть сокет на стороне сервера, но я не могу его использовать. Также я попробовал следующее:
1) Отправить 0 Длина в конце отправки способ сказать клиенту, что длина равна нулю:

send(sockfd, NULL, NULL, 0); 

2) Определить флаги и отправить:

#define MSG_FIN 0x200 
#define MSG_EOR 0x0080 

и снова с обоими флагами:

send(sockfd, NULL, NULL, MSG_FIN); 
send(sockfd, NULL, NULL, MSG_EOR); 

Кто-нибудь, пожалуйста, помогите, что я делаю неправильно здесь? Спасибо

+2

Я знаю, что вы сказали, что не можете его использовать, но _why_ вы не можете закрыть сокет на сервере? Если вы не хотите закрыть его, разве это не означает, что вы собираетесь отправить что-то еще позже? И если это так, то Java все равно сможет читать, не так ли? –

+0

Возможно, вам захочется выяснить, сколько байтов вы собираетесь отправить, и префикс ваших данных с этим номером, чтобы клиент мог определить, когда прекратить чтение. Это похоже на заголовок ['Content-Length'] (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13) в HTTP. –

+0

Если вам нужно отправлять отдельные «сообщения» по TCP-соединению, это проблема на уровне приложений, которую вы должны реализовать и обработать самостоятельно. TCP действительно не относится к этому. (UDP делает, но его ненадежность, вероятно, делает его непригодным для вашего случая использования. То есть, не потоковая передача мультимедиа или P2P.) – millimoose

ответ

5

Если вы хотите отправлять прерывистые данные через один и тот же TCP-сокет, вам нужно будет кодировать границы информации, которую вы отправляете, в отправляемых вами данных. Примером этого является отправка «пакетов» данных с префиксом длины, так что получатель пакета будет считывать столько байтов сокета, сколько говорит префикс длины.

+0

+1 Единственное, что знает ретривер, это конец потока. Если вы хотите, чтобы он знал о «сообщениях», вам нужно добавить протокол для этого. например отправьте длину 4 байта перед каждым сообщением, чтобы он знал, сколько нужно читать. –

+0

Теперь я сначала отправляю несколько строк файла, затем строки и клиент читают столько раз, сколько говорит число. благодаря –

0

У вас есть две проблемы с вашим читателем. Вы предполагаете, что вы всегда будете читать полный буфер. Вы не можете предположить это, если только вы читаете только один байт за раз. Вы также предполагаете, что вы всегда будете читать целые многобайтные символы, это вряд ли будет истинным, если вы никогда не используете многобайтовые символы.

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

BufferedReader br = new BufferedReader(new InputStreamReader(
         Client.getCl().getInputStream(), "UTF-8")); 
for(String line; (line = br.readLine()) != null;) { 
    // process a whole line of text at once. e.g. 
    System.out.println(line); 
} 

Это расшифровывает текст, считывает целые строки и обрабатывает любые многобайтовые символы.

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