DataOutputStream не сбрасывается - PullRequest
0 голосов
/ 05 декабря 2009

У меня есть Java-клиент, который отправляет строки UTF-8 на TCP-сервер C #, я использую DataOutputStream для отправки строк. Код выглядит так:

public void sendUTF8String(String ar) {
    if (socket.isConnected()) {
        try {
            dataOutputStream.write(ar.getBytes(Charset.forName("UTF-8")));
            dataOutputStream.flush();
        } catch (IOException e) {
            handleException(e);
        }
    }
}

Проблема в том, что флеш не работает правильно. Если я отправляю две строки близко друг к другу, сервер получает только одно сообщение с обеими строками. Все это работает, если я делаю Thread.sleep (1000) между вызовами, это, очевидно, не является решением. Чего мне не хватает?

Ответы [ 3 ]

7 голосов
/ 05 декабря 2009

flush() не гарантирует отправку пакета данных. Ваш стек TCP / IP свободен для объединения ваших данных для максимальной эффективности. Хуже того, между вами и вашим пунктом назначения, вероятно, есть множество других стеков TCP / IP, и они могут делать то же самое.

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

2 голосов
/ 05 декабря 2009

Вам не нужно беспокоиться о том, как данные разбиваются на пакеты.

Вы должны включить длину строки в свои сообщения, а затем на принимающей стороне вы сначала прочитаете длину. Так, например, для отправки вы бы сделали

byte[] arbytes = ar.getBytes(Charset.forName("UTF-8"));
output.writeInt(arbytes.length)
output.write(arbytes)

, а затем в вашем читателе вы делаете

byte[] arbytes = new byte[input.readInt()];
for(int i = 0; i < len; i++){
     arbytes[i] = input.read();
}
//convert bytes back to string.

Вы не можете просто вызвать input.read (arbytes), потому что функция read не обязательно считывает всю длину массива. Вы можете сделать цикл, где вы читаете порцию за раз, но код для этого немного сложнее.

В любом случае, вы поняли идею.


Кроме того, если вы действительно хотите управлять тем, что входит в какие пакеты, вы можете использовать Datagram Sockets , но если вы это сделаете, то доставка пакета не гарантируется.

1 голос
/ 06 декабря 2009

Сокет отправляет поток данных, а не сообщений. Вы не должны полагаться на получаемые пакеты того же размера, что и отправленные. Пакеты могут быть сгруппированы вместе, как вы видели, но они также могут быть разбиты. Воспользуйтесь предложением @Chad Okere, чтобы убедиться, что вы получаете блоки одинаково, если они отправлены.

Однако в вашем случае вы можете просто использовать

dataOutputStream.writeUTF(ar); // sends a string as UTF-8

и

String text = dataInputStream.readUTF(); // reads a string as UTF-8
...