Есть ли разница в writeInt Java при выполнении в Windows по сравнению с Mac на базе Intel - PullRequest
0 голосов
/ 07 апреля 2011

Я сейчас пишу сервер Java TCP для обработки связи с клиентом (который я не писал). Когда сервер, размещенный в Windows, отвечает клиенту количеством полученных записей, клиент неправильно читает целое число и вместо этого читает его как пустой пакет. Когда тот же код сервера, размещенный на моем Mac, отвечает клиенту с количеством полученных записей, клиент читает пакет и отвечает правильно. Благодаря моему исследованию я не нашел объяснения, которое, кажется, решает проблему. Я попытался сторнировать байты (Integer.reverseBytes) перед вызовом метода writeInt, но это, похоже, не решило проблему. Любые идеи приветствуются.

Brian

После сравнения файлов pcap нет очевидных различий в том, как они отправляются. Отправляется первый байт, за которым следуют последние 3. Обе системы отправляют правильное количество записей.

Да, я имею в виду метод DataOutputStream.writeInt (). // Код добавлен

 public void run() {
try {
        InputStream in = socket.getInputStream();
        DataOutputStream datOut = new DataOutputStream(socket.getOutputStream());

        datOut.writeByte(1); //sends correctly and read correctly by client
        datOut.flush();

        //below is used to read bytes to determine length of message

        int bytesRead=0;
        int bytesToRead=25;
        byte[] input = new byte[bytesToRead];
        while (bytesRead < bytesToRead) {
            int result = in.read(input, bytesRead, bytesToRead - bytesRead);
            if (result == -1) break;
            bytesRead += result;
       }
        try {
                inputLine = getHexString(input);
                String hexLength = inputLine.substring(46, 50);
                System.out.println("hexLength: " + hexLength);
                System.out.println(inputLine);

                //used to read entire sent message

                bytesRead = 0;
                bytesToRead = Integer.parseInt(hexLength, 16);
                System.out.println("bytes to read " + bytesToRead);
                byte[] dataInput = new byte[bytesToRead];
                while (bytesRead < bytesToRead) {
                    int result = in.read(dataInput, bytesRead, bytesToRead - bytesRead);
                    if (result == -1) break;
                    bytesRead += result;
                }

                String data = getHexString(dataInput);
                System.out.println(data);

                //Sends received data to class to process

                ProcessTel dataValues= new ProcessTel(data);
                String[] dataArray = new String[10];
                dataArray = dataValues.dataArray();

                //assigns returned number of records to be written to client

                int towrite = Integer.parseInt(dataArray[0].trim());

                //Same write method on Windows & Mac...works on Mac but not Windows

                datOut.writeInt(towrite);

                System.out.println("Returned number of records: " + Integer.parseInt(dataArray[0].trim()) );
                datOut.flush();
            } catch (Exception ex) {
                Logger.getLogger(ServerThread.class.getName()).log(Level.SEVERE, null, ex);
            }
    datOut.close();
    in.close();
    socket.close();

} catch (IOException e) {
    e.printStackTrace();
}

}

Ответы [ 3 ]

1 голос
/ 07 апреля 2011

Как описано в Javadoc, DataOutputStream.writeInt () использует сетевой порядок байтов в соответствии с RFC TCP / IP. Это тот метод, на который вы ссылаетесь?

0 голосов
/ 08 апреля 2011

Некоторые общие комментарии к вашему коду:

int bytesRead=0;
int bytesToRead=25;
byte[] input = new byte[bytesToRead];
while (bytesRead < bytesToRead) {
    int result = in.read(input, bytesRead, bytesToRead - bytesRead);
    if (result == -1) break;
    bytesRead += result;
}

Эта обработка EOF является обманчивой.Это означает, что вы не знаете, действительно ли вы прочитали полные 25 байтов.И если вы этого не сделаете, вы предположите, что число байтов для отправки равно 0.

Хуже, вы копируете и вставляете этот код ниже, полагаясь на правильную инициализацию тех же переменных.Если есть опечатка, вы никогда не будете знать это.Вы можете преобразовать его в свой собственный метод ( с тестами ), или вы можете вызвать DataInputStream.readFully().

inputLine = getHexString(input);
String hexLength = inputLine.substring(46, 50);

Вы конвертируете в гекс, чтобы извлечь целое число?Зачем?И что еще более важно, если у вас есть какие-либо проблемы с порядком байтов, это, вероятно, причина

Я изначально собирался рекомендовать использовать ByteBuffer для извлечения значений, но на второй взгляд я думаю, что выследует обернуть ваш входной поток с DataInputStream.Это позволило бы вам читать полные буферы byte[] без необходимости в цикле, и это позволило бы вам избавиться от преобразований байтов в шестнадцатеричные числа: вы просто вызывали бы readInt().

Но, продолжая:

String[] dataArray = new String[10];
dataArray = dataValues.dataArray();

Вы понимаете, что new String[10] выбрасывается на следующей строке?Это то, что вы хотите?

int towrite = Integer.parseInt(dataArray[0].trim());

datOut.writeInt(towrite);

System.out.println("Returned number of records: " + Integer.parseInt(dataArray[0].trim()) );

Если вы используете операторы логирования, выведите то, что вы на самом деле используете (towrite).Не пересчитывайте это.Слишком велика вероятность ошибиться.

} catch (Exception ex) {
    Logger.getLogger(ServerThread.class.getName()).log(Level.SEVERE, null, ex);
}

// ...

} catch (IOException e) {
    e.printStackTrace();
}

Вызывается ли один или оба из этих блоков улова?И почему они отправляют свою продукцию в разные места?В этом отношении, если у вас есть регистратор, почему вы вставляете операторы System.out.println()?

0 голосов
/ 07 апреля 2011

Нет, процессоры x86 поддерживают только порядок байтов с прямым порядком байтов, он не зависит от ОС.Что-то еще не так.

Я предлагаю использовать wireshark для захвата потока с рабочего сервера Mac и нерабочего сервера Windows и сравнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...