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

时间:2018-12-05 13:20:52

标签: java c# sockets

我一直在尝试创建一个可以相互通信的 Java C#应用。在这种情况下,用户从 C#端发送一个String,它应该显示在 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 :(得分:1)

您的问题是您在Java中使用DataInputStream / DataOutputStream,这些语言使用了特定于Java的类似XDR的数据类型序列化协议。您没有在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字节,这些字节永远不会到达。