#java #c #sockets
#java #c #сокеты
Вопрос:
У меня есть приложение, которое постоянно извлекает входные данные на Java из буфера кадров и отправляет их по проводам в приложение на C .
У меня возникли проблемы на стороне получателя. Я пытаюсь отправить один пакет (или, по крайней мере, позволить TCP реконструировать его как один пакет) для каждого буфера кадров. Буфер кадров разбивается на несколько небольших пакетов на принимающей стороне.
Код Java выглядит следующим образом:
OutputStream os = clientSocket.getOutputStream();
FileInputStream fos = new FileInputStream("fb");
while (true) {
int nb = fos.read(buff);
if (nb <= 0)
break;
os.write(buff, 0, nb);
}
fos.close();
os.close();
На стороне клиента я пытаюсь прочитать тот же объем. nb и size здесь имеют одинаковое значение:
n = read(sockfd, buffer, size);
while (n > 0) {
// We have a new frame
fprintf(stderr, "New frame: %dn", n);
n = read(sockfd, buffer, size);
}
Печатаемое значение n намного меньше размера. Он получает много пакетов, когда я надеюсь, что возврат из read () будет пакетом размера ‘size’ (или nb).
Кто-нибудь, пожалуйста, знает, почему это так, пожалуйста?
Большое вам спасибо за вашу помощь!
Ответ №1:
У вас нет контроля над размерами фреймов TCP. Сетевые устройства могут и фрагментировать пакеты, чтобы вы получали больше пакетов, чем отправляли.
Слово «поток» используется по очень веской причине. Вы получаете поток байтов, но кадрирование отсутствует, если приложение-отправитель и получатель не накладывают кадрирование на поток, включая маркеры кадров в данные. Один из распространенных способов, используемых многими протоколами TCP, — использовать rn
в качестве маркера фрейма. Это означает, что получатель собирает входящие данные, но не обрабатывает их, пока не встретит маркер фрейма. В этот момент получатель обрабатывает один кадр, а затем продолжает поиск маркера следующего кадра.
Одна вещь, которую вам следует рассмотреть, — это использование кросс-платформенной кросс-языковой библиотеки, такой как ZeroMQ, для обработки фрейминга для вас.
Комментарии:
1. О, я понимаю. Я думал, что фрагментация происходит на более низком уровне, а не приложение (т.е.: write() может фрагментировать данные на более низком уровне, но read() вернет данные только при дефрагментации нижним уровнем. Я не думаю, что r n будет работать в моем случае, поскольку я использую необработанные данные. Будет ли это? Я могу просто сохранить счетчик, и когда я достигну «размера», я знаю, что это фрейм. Я изучу ZeroMQ. Большое спасибо за вашу помощь.
2. На самом деле, ZeroMQ использует количество байтов, и это будет работать нормально. Посмотрите на протокол memcache, который использует как r n, так и количество байтов в зависимости от того, в каком режиме он находится. code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt