Przeróbka programu z C# do Javy

0

Witam. Robię mały program w Javie, który działa następująco: mam odpalony symulator, który generuje mi wynik pomiaru. Odpalam go, podając IP komputera oraz port 10000. Program po otrzymaniu stringa 1 wysyła wartość napięcia zaś 2 prądu. W C# program działa, natomiast w Javie zawsze zwraca mi zero. Nie wiem gdzie jest błąd. W załączeniu jest archiwum z symulatorem (Nie ja go pisałem). Poniżej kody:

Program w C# (DZIAŁAJĄCY):

using System;
using System.IO;
using System.Net.Sockets;
namespace ConsoleMetexEthCLient
{
 class Program
 {
 static void Main(string[] args)
 {
 try
 {
 TcpClient client = new TcpClient();
 client.Connect(IPAddress.Parse("192.168.1.113"), 10000);
//Adres serwera do ustawienia
 NetworkStream stream = client.GetStream(); //pobranie strumienia
 BinaryWriter SWrite = new BinaryWriter(stream);//strumien zapisu
 BinaryReader Sread = new BinaryReader(stream); //strumien odczytu
 Console.WriteLine("Napisz polecenie. '0' Konczy polaczenie, 1 i 2
pyta o wynik pomiaru");
 while (true)
 {
 Console.Write("Podaj komendę>");
 String message = Console.ReadLine(); //czyta klawiature
 SWrite.Write(Convert.ToByte(message));
//zamienia na int i wysyla
 if ((message == "0")) break; //koniec programu
 int response = Sread.ReadInt16();
//odczyt odpowiedzi w postaci int
 Console.WriteLine("Odb: {0}", response); //wypisanie na ekran
 }
 stream.Close();// Zamyka strumienie
 client.Close();
 }
 catch (SocketException e)
 {//obsluga wyjatku
Console.WriteLine("SocketException: {0}", e);
 }
 }
 }
}

Program w Javie (DZIAŁA NIEPOPRAWNIE):

package com.company;

import java.net.*;
import java.io.*;

import java.util.concurrent.TimeUnit;

public class Main {

    public static void main(String[] args) {
	// write your code here
        Socket my_socket = null;

        try{
            my_socket = new Socket("192.168.0.27", 10000);
            // get the output stream from the socket.
            OutputStream outputStream = my_socket.getOutputStream();
            // create a data output stream from the output stream so we can send data through it
            DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
            InputStream in = my_socket.getInputStream();
            int data = -1;


            while(true){
                dataOutputStream.write("1".getBytes());//wyślij jedynkę "1"
                dataOutputStream.flush(); // send the message

                data = in.read();


                System.out.println("The voltage value is " + data + " V ");

                TimeUnit.SECONDS.sleep(1);
            }
            //dataOutputStream.close(); // close the output stream when we're done.
            //in.close();
            //my_socket.close();

        }
        catch(UnknownHostException my_unknown_exception){
            System.out.println(my_unknown_exception);
        }
        catch(IOException my_input_exception){
            System.out.println(my_input_exception);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }


    }
}
0

W wersji C# robisz int response = Sread.ReadInt16(); czyli wczytujesz 2 bajty, a w wersji Javowej robisz data = in.read(); czyli wczytujesz jeden bajt.

0
 data = in.read();

Bierze byte, niech cię deklaracja nie zmyli - natomiast

ReadInt16()

bierze 2 byte jako int16

Generalnie przepisywanie z języka na język jest pozornie łatwe, ale potknąć się można w bardzo wielu miejscach. JAk z językami naturalnymi: idiomy jednego języka nie są idiomami w innym

0

Okej poprawiłem trochę to i odczytuje mi teraz poprawnie wartość, ale tylko jak odczytam na raz jeden bajt. Jak odczytuję dwa bajty to zwraca mi zawsze wartość 4096. Nie rozumiem jak mam to zrobić bo przy odczycie dwóch bajtów naraz wyrzuca wartość 4096. Trochę to wygląda jakby najpierw odczytywał drugi bajt a potem pierwszy. W załączeniu zrzut i tak wygląda teraz program, który działa poprawnie co drugą iterację:
package com.company;

import java.net.;
import java.io.
;

import java.util.concurrent.TimeUnit;

public class Main {

public static void main(String[] args) {
// write your code here
    Socket my_socket = null;

    try{
        my_socket = new Socket("192.168.0.27", 10000);
        // get the output stream from the socket.
        OutputStream outputStream = my_socket.getOutputStream();
        // create a data output stream from the output stream so we can send data through it
        DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
        InputStream in = my_socket.getInputStream();
        DataInputStream dataInputStream = new DataInputStream(in);
        int data = 20;
        //byte[] buffer = new byte[2];
        while(true){
            dataOutputStream.write(1);//wyślij jedynkę "1"
            dataOutputStream.flush(); // send the message
            data=dataInputStream.read();
            //data = in.read(buffer);
            //data =in.read

            System.out.println("The voltage value is " + data + " V ");

            TimeUnit.SECONDS.sleep(1);
        }
        //dataOutputStream.close(); // close the output stream when we're done.
        //in.close();
        //my_socket.close();

    }
    catch(UnknownHostException my_unknown_exception){
        System.out.println(my_unknown_exception);
    }
    catch(IOException my_input_exception){
        System.out.println(my_input_exception);
    }
    catch (InterruptedException e) {
        e.printStackTrace();
    }


}

}

0

Jakie jest https://en.wikipedia.org/wiki/Endianness strumienia do którego się łączysz?

0
Wibowit napisał(a):

Jakie jest https://en.wikipedia.org/wiki/Endianness strumienia do którego się łączysz?

W sumie to nie do końca rozumiem w jakiej kolejności są te bajty wysyłane. Bo teoretycznie pierwszy bajt powinien zawierać wynik pomiaru ( i tak jest jak odczytuje naraz tylko jeden bajt, a drugi wynnosi zero). Ale jak chcę odczytać dwa to dzieją się jakieś głupoty. Chociaż jak w tym symulatorze zadam wartość 4 to wysyła dwa i potem też dwa.

0

A jak użyjesz readShort albo readUnsignedShort to dostaniesz dobre wartości?

0

Chyba ta współpraca C# i Java jakoś nie chce działać :-)

Nie. Po prostu to tłumaczenie kodu z C# na Javę zaprezentowane tutaj to kalectwo. Wygląda jakbyś w ogóle nie patrzył na dokumentację. W jednej wersji wczytujesz 1 bajt, w drugiej wczytujesz 2 bajty.

W jednej wersji robisz:

 String message = Console.ReadLine(); //czyta klawiature
 SWrite.Write(Convert.ToByte(message));

czyli zapisujesz do strumienia jeden bajt będący sparsowaną liczbą z wejścia, a w drugiej wersji robisz:

                dataOutputStream.write("1".getBytes());//wyślij jedynkę "1"

czyli wysyłasz kod ASCII znaku 1 zamiast faktycznie wartości 1, aczkolwiek widzę, że w najnowszej wersji to poprawiłeś.

https://docs.microsoft.com/pl-pl/dotnet/api/system.io.binaryreader.readint16?view=netframework-4.8#System_IO_BinaryReader_ReadInt16
BinaryReader reads this data type in little-endian format.

java.io.DataInputStream jest natomiast big-endian. Używanie little-endian w środowisku sieciowym to jakieś nieporozumienie. Jednak jeśli jest to wymuszone to można użyć np com.google.common.io.LittleEndianDataInputStream czy czegoś podobnego. W twoim prostym przypadku można też użyć java.lang.Short.reverseBytes do ręcznego odwrócenia kolejności bajtów, ale jeśli będziesz miał tego dużo to opłaca się skorzystać z np tego gotowca od Google'a.

1 użytkowników online, w tym zalogowanych: 0, gości: 1