C++套接字 - wstring 到 Java 套接字

C++ socket - wstring to Java socket

本文关键字:套接字 Java C++ wstring      更新时间:2023-10-16

我有一个带有自定义协议的服务器(用于即时消息 - 该协议已经在桌面客户端上就位),我目前正在尝试在 Android 应用程序上实现它。

我已经设法打开服务器的套接字并发送一个 4 字节整数,但是,我无法让 Java 发送字符串或从服务器(正确)接收字符串。

服务器是用C++编写的,托管在Windows机器上,它使用wstring进行通信(以允许发送非ASCII字符)。如何让应用程序以正确的格式读取/写入套接字?我相信在这种用法中,wstring 应该是 UTF-16 字符串,但我不确定字节序。

到目前为止,这是Java代码(我在测试时暂时禁用了NetworkOnMainThread异常):

private String recv_from_server() {
    String ret = "";
    char[] bytes = new char[8192];
    try {
        int in = sinput.read(bytes, 0, 8192);
        if(in > 0) {
            byte[] str = bytes.toString().getBytes("UTF-8");
            ret = new String(str, "UTF-8");
        }
    }
    catch(Exception ex) {}
    return ret;
}

private void send_to_server(String message) {
    try {
        soutput.write(message);
        soutput.flush();
    }
    catch(Exception ex) {
        ((TextView)findViewById(R.id.chat_message_message)).setText(ex.toString());
    }
}
@Override
protected void onStart() {
    super.onStart();
    refresh();
    refresher = new Timer();
    refresher.schedule(new RefresherEvt(), 15000);
    if(open_connection() == true) {
        String ret = "";
        while(ret == "") {
            ret = recv_from_server();
        }
        ((TextView)findViewById(R.id.chat_message_message)).setText(ret);
        send_to_server("test message");
    }
}

我从recv_from_server函数获取垃圾数据,而发送函数似乎从未到达服务器。

提前谢谢。

此代码:

byte[] str = bytes.toString().getBytes("UTF-8");
ret = new String(str, "UTF-8");

将只返回一个形式为 "[B@nnnnnn" 的字符串,因为char[]不会覆盖Object.toString(). 双重转换也不会完成任何有用的事情。当然,char[]数组应该被称为chars,而不是bytes。它应该是:

return new String(chars, 0, in, "UTF-8"); // or UTF-16 or whatever you determine

我假设sinput是围绕输入流的BufferedReader?否则,您的代码将无法编译。

首先:这个变量的名称肯定令人困惑

char[] bytes = new char[8192];

它和称为字节的字符数组在 JAVA 下绝对不是一回事。

第二:我不知道你在这里用的是哪种流。有些可能会直接读取字符,有些可能会在内部从 UTF-8 转换为 UTF-16 等......等。。

int in = sinput.read(bytes, 0, 8192);  

但是第三:据我所知,这没有任何作用:

byte[] str = bytes.toString().getBytes("UTF-8");
ret = new String(str, "UTF-8");

假设您有一个有效的 bytes 字符串(实际上是字符),并将其转换为 UTF-8 编码的字节数组(称为 str)。然后,您将它从 UTF-8 转换回 JAVA 内部 UTF-16 编码,ret .为什么不直接返回bytes.toString()

一种可能性

你说 C 代码中的字符串是 wstring aka. 基于 UTF-16 或 UCS2。 据我所知,适用于Windows。因此,一个假设是您收到的数据是 UTF-16 编码的,如果它实际上是 UCS2,您仍将覆盖 BMP 中的所有字符。所以我要尝试的第一件事是直接从 UTF-16 解码它,如下所示:

byte[] bytes = new byte[BUFFERSIZE];
// Actually read bytes -- don't know
// if your stream can handle that
int n sinput.read(bytes,0,BUFFERSIZE);
// silently assume n % 2 == 0 and UTF-16 doesn't use surrogates
String str = new String(bytes,n,"UTF16-BE" /*"UTF16-LE"*/);

然而

std::wstring 格式大多数时候仅用于字符串的内部表示,因为对于大多数字符,一个字符都有一个字符串位置。您不必与可变长度的编码作斗争。对于UCS4完全正确,对于UTF-16几乎是正确的。这在内部给了它很大的优势。但对于外部表示又名。文件或互联网 UTF-8 是通用语言,因为它是紧凑的,不关心字节序,ASCII 仍然可见为 ASCII,没有任何穿插的零字节。等等。

因此,即使没有看到 C 代码,我仍然会假设外部表示很有可能是 UTF-8。在这种情况下,您只需执行以下操作:

byte[] bytes = new byte[BUFFERSIZE];
// Actually read bytes -- don't know
// if your stream can handle that
sinput.read(bytes,0,BUFFERSIZE);
String str = new String(bytes,BUFFERSIZE,"UTF8");

对于您的 soutput.write(...),您还必须调用 getBytes("UTF8")