简体   繁体   English

无法让 Java 和 C# 通过套接字进行通信

[英]Can't get Java and C# to communicate through sockets

I've been trying to create a Java and C# app that would communicate together.我一直在尝试创建一个可以一起通信的JavaC#应用程序。 In this case the user sends a String from the C# side, it should display on the Java console and echo back.在这种情况下,用户从C#端发送一个String ,它应该显示在Java控制台上并回显。 Unfortunately, I have only been able to establish the connection, without being able to send or receive anything.不幸的是,我只能建立连接,无法发送或接收任何内容。

Java code snippet: 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# snippet: 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();

        }

Your problem is that you're using DataInputStream / DataOutputStream in Java, which use a Java-specific, XDR-like datatype serialization protocol.您的问题是您在 Java 中使用DataInputStream / DataOutputStream ,它使用 Java 特定的、类似 XDR 的数据类型序列化协议。 You are not using that protocol at your C# side.您没有在 C# 端使用该协议。

Switching to using the raw input/output stream should be sufficient (although very brittle).切换到使用原始输入/输出流应该就足够了(尽管非常脆弱)。 However, notice that as you are sending raw bytes from C#, it will be impossible to tell for the recipient when the message is complete.但是,请注意,当您从 C# 发送原始字节时,将无法告诉接收者消息何时完成。 It would be better to send the number of bytes of the message, followed by the actual message (this is what DataInputStream / DataOutputStream does, but it comes with additional considerations that you would need to correctly implement in your C# side, for example readUTF / writeUTF use a 'modified UTF-8' format instead of normal UTF-8).最好先发送消息的字节数,然后是实际消息(这就是DataInputStream / DataOutputStream所做的,但它带有额外的注意事项,您需要在 C# 端正确实现,例如readUTF / writeUTF使用“修改后的 UTF-8”格式而不是普通的 UTF-8)。

The problem right now, is that you send raw bytes from C#, the readUTF() method reads the first two bytes as length, and then tries to read a message of that length.现在的问题是,您从 C# 发送原始字节, readUTF()方法读取前两个字节作为长度,然后尝试读取该长度的消息。 For example if C# sends "Hello" (encoded as 0x48, 0x65, 0x6c, 0x6c, 0x6f), then the Java side will read 0x48, 0x65 ("He") as "message length is 18533" and then tries to read 18533 bytes, while the actual remaining bytes are only 3 (the "llo").例如,如果 C# 发送“Hello”(编码为 0x48、0x65、0x6c、0x6c、0x6f),那么 Java 端将读取 0x48、0x65(“He”)为“消息长度为 18533”,然后尝试读取 18533 个字节,而实际剩余的字节只有 3 个(“llo”)。 This causes the input to block waiting for the remaining 18530 bytes, which never arrive.这会导致输入阻塞等待剩余的 18530 个字节,这些字节永远不会到达。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM