Не удается заставить Java и C # общаться через сокеты - PullRequest
0 голосов
/ 05 декабря 2018

Я пытался создать приложение Java и C # , которое будет взаимодействовать друг с другом.В этом случае пользователь отправляет String со стороны C # , он должен отображаться на консоли Java и возвращаться назад.К сожалению, я смог установить соединение только без возможности что-либо отправлять или получать.

Фрагмент кода Java:

public CommunicationThreadHandler(Socket socket, CarList carList) {
    this.socket = socket;
    this.carList = carList;
    try {
        this.in = new DataInputStream(socket.getInputStream());
        this.out = new DataOutputStream(socket.getOutputStream());
        this.writer = new Writer(out);
    } catch (IOException e) {
        System.out.println("Exception when reading or receiving data!");
        e.printStackTrace();
    }
    this.ip = socket.getRemoteSocketAddress().toString();
}

@Override
public void run() {
    while (true) {
        try {
            Gson gson = new Gson();
            String msgJson = in.readUTF();
            String msg = gson.fromJson(msgJson,String.class);
            System.out.println("Message from C# client: "+msg);
            String reply = "Server echo: "+msg;
            String replyJson = gson.toJson(reply);
            out.writeUTF(replyJson);
            if (msg.equals(Package.EXIT))
                break;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Фрагмент кода C #:

public static void StartClient()
{
    // Data buffer for incoming data.  
    byte[] bytes = new byte[1024];

    // Connect to a remote device.  
    try
    {
        // Establish the remote endpoint for the socket.  
        // This example uses port 11000 on the local computer.  
        IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
        IPAddress ipAddress = ipHostInfo.AddressList[0];
        IPEndPoint remoteEP = new IPEndPoint(ipAddress, 11000);

        // Create a TCP/IP  socket.  
        Socket sender = new Socket(ipAddress.AddressFamily,
            SocketType.Stream, ProtocolType.Tcp);

        // Connect the socket to the remote endpoint. Catch any errors.  
        try
        { 
            sender.Connect(remoteEP);

            Console.WriteLine("Socket connected to {0}",
                sender.RemoteEndPoint.ToString());
            while (true)
            {
                Console.Write("Enter message to server: ");

                string message = Console.ReadLine();
                Console.WriteLine($"To be sent: {message}");

                // Encode the data string into a byte array.  
                byte[] msg = Encoding.ASCII.GetBytes(message);

                // Send the data through the socket.  
                int bytesSent = sender.Send(msg);

                // Receive the response from the remote device.  
                int bytesRec = sender.Receive(bytes);

                string msgFromServer = Encoding.ASCII.GetString(bytes, 0, bytesRec);

                if (msgFromServer.Equals("EXIT"))
                    break;

                Console.WriteLine($"Server says: {msgFromServer}");
            }
            // Release the socket.

            sender.Shutdown(SocketShutdown.Both);
            sender.Close();

        }

1 Ответ

0 голосов
/ 05 декабря 2018

Ваша проблема в том, что вы используете DataInputStream / DataOutputStream в Java, которая использует специфичный для Java протокол сериализации типа XDR-like.Вы не используете этот протокол на вашей стороне C #.

Переключение на использование необработанного потока ввода-вывода должно быть достаточным (хотя и очень хрупким).Однако обратите внимание, что, поскольку вы отправляете необработанные байты из C #, получателю будет невозможно определить, когда сообщение будет завершено.Было бы лучше послать количество байтов сообщения, за которым следует реальное сообщение (это то, что делает DataInputStream / DataOutputStream, но это связано с дополнительными соображениями, которые вам необходимо правильно реализовать на вашей стороне C #,например, readUTF / writeUTF использует «модифицированный формат UTF-8» вместо обычного UTF-8).

Проблема сейчас в том, что вы отправляете необработанные байты из C #, readUTF()Метод читает первые два байта как длину, а затем пытается прочитать сообщение этой длины.Например, если C # отправляет «Hello» (кодируется как 0x48, 0x65, 0x6c, 0x6c, 0x6f), то сторона Java будет читать 0x48, 0x65 («He») как «длина сообщения 18533», а затем пытается прочитать 18533 байтав то время как фактические оставшиеся байты - только 3 ("llo").Это приводит к тому, что вход блокирует ожидание оставшихся 18530 байтов, которые никогда не поступают.

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