DataOutputStream: dos.write () в цикле, Receiver получает только один пакет данных - PullRequest
0 голосов
/ 16 мая 2019

У меня проблема с моим TCP-соединением. Я отправляю данные (простую строку) через смартфон на планшет через соединение через сокет TCP. Соединение работает нормально и данные передаются как положено. Но когда я выполняю цикл и в каждой итерации dos.write () запускается, только один пакет поступает в приемник данных планшетов. Что я делаю не так?

Вот отправляющая часть моего соединения. Он перебирает список и записывает все данные в DataOutputStream.

for(int i = 0; i <= logList.length - 1; ++i){
    String backupPayload = invertLogStringToJson(logList[i]);

    dos = new DataOutputStream(s.getOutputStream());

    dos.writeUTF(backupPayload);
    dos.flush();
    dos.close();

На планшете я получаю данные через этот фрагмент кода:

@Override
public void run() {
    try {

        while(true){
            mySocket = ss.accept();
            dis = new DataInputStream(mySocket.getInputStream());
            message = dis.readUTF();

            handler.post(() -> {
                bufferIntentSendCode.putExtra("data", message);
                ctx.sendBroadcast(bufferIntentSendCode);
            });
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Как я уже сказал, соединение работает нормально, когда я отправляю только один пакет данных. Но если я хочу отправить несколько пакетов внутри цикла, в пункт назначения прибудет только первый пакет.

Кто-нибудь может мне помочь? :)

1 Ответ

1 голос
/ 17 мая 2019

Вызов close() для DataOutputStream закрывает связанный с ним OutputStream, а закрытие сокета OutputStream закрывает сокет.Это задокументированное поведение.

Но это должно быть в порядке, потому что ваш код получателя ожидает только одну строку в любом случае.Вы звоните dis.readUTF() только один раз за TCP-соединение.

Если вы хотите отправить несколько строк в одном соединении, НЕ звоните dos.close() на стороне отправителя (по крайней мере, до тех пор, пока не будут выполнены все строкии DO вызовет dis.readUTF() в цикле на принимающей стороне, пока все строки не будут получены.

dos = new DataOutputStream(s.getOutputStream());

for(int i = 0; i < logList.length; ++i){
    String backupPayload = invertLogStringToJson(logList[i]);
    dos.writeUTF(backupPayload);
}
dos.flush();

dos.close();
@Override
public void run() {
    try {
        while (true) {
            mySocket = ss.accept();
            dis = new DataInputStream(mySocket.getInputStream());

            try {
                while (true) {
                    message = dis.readUTF();
                    handler.post(() -> {
                        bufferIntentSendCode.putExtra("data", message);
                        ctx.sendBroadcast(bufferIntentSendCode);
                    });
                }
            } catch (IOException e) {
            }

            dis.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

В качестве альтернативы, передайте длину списка перед отправкой фактических строк, изатем прочитайте длину, прежде чем читать строки:

dos = new DataOutputStream(s.getOutputStream());

// maybe other things first...

dos.writeInt(logList.length);
for(int i = 0; i < logList.length; ++i){
    String backupPayload = invertLogStringToJson(logList[i]);
    dos.writeUTF(backupPayload);
}
dos.flush();

// maybe other things next...

dos.close();
@Override
public void run() {
    try {
        while (true) {
            mySocket = ss.accept();
            dis = new DataInputStream(mySocket.getInputStream());

            try {
                // maybe other things first...

                int length = dis.readInt();
                for (int i = 0; i < length; ++i) {
                    message = dis.readUTF();
                    handler.post(() -> {
                        bufferIntentSendCode.putExtra("data", message);
                        ctx.sendBroadcast(bufferIntentSendCode);
                    });
                }

                // maybe other things next...

            } catch (IOException e) {
            }

            dis.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
...