Сергей, возможно, был прав насчет потери данных внутри буфера, но я не уверен в его объяснении.(BufferedReaders обычно не хранит данные внутри своих буферов. Возможно, он думает о проблеме с BufferedWriters, которая может потерять данные, если основной поток преждевременно завершит работу.) [Не берите в голову;Я неправильно понял ответ Сергея.В остальном это действительно AFAIK.]
Я думаю, что у вас есть проблема, характерная для вашего приложения.В вашем коде клиента вы начинаете читать следующим образом:
public static void recv(Socket socket){
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//...
int numFiles = Integer.parseInt(in.readLine());
... и продолжаете использовать in
для начала обмена.Но затем вы переключаетесь на использование необработанного потока сокетов:
while(bytesRead > fileSize){
read = socket.getInputStream().read(buffer);
Поскольку in
является BufferedReader, он уже собирается заполнить свой буфер до 8192 байтов из входного потока сокета.Любые байты, которые находятся в этом буфере и которые вы не читаете из in
, будут потеряны.Ваше приложение зависает, потому что считает, что сервер удерживает некоторые байты, но на сервере их нет.
Решение состоит в том, чтобы не выполнять побайтные чтения из сокета (ой!плохой процессор!), но использовать BufferedReader последовательно.Или, чтобы использовать буферизацию с двоичными данными, замените BufferedReader на BufferedInputStream, который обертывает InputStream сокета.
Кстати, TCP не так надежен, как полагают многие.Например, когда сокет сервера закрывается, он может записать данные в сокет, которые затем теряются при отключении соединения сокета.Вызов Socket.setSoLinger может помочь предотвратить эту проблему.
РЕДАКТИРОВАТЬ: Кстати, вы играете с огнем, обрабатывая данные байтов и символов, как если бы онивзаимозаменяемы, как вы делаете ниже.Если данные действительно являются двоичными, то преобразование в строку может привести к повреждению данных.Возможно, вы хотите записывать в BufferedOutputStream?
// Java is retarded and reading and writing operate with
// fundamentally different types. So we write a String of
// binary data.
fileWriter.write(new String(buffer));
bytesRead += read;
EDIT 2 : уточнено (или попытались уточнить: -} обработка двоичных и строковых данных.