hoijui / JavaOSC

OSC content format/"protocol" library for JVM languages
http://www.illposed.com/software/javaosc.html
BSD 3-Clause "New" or "Revised" License
156 stars 43 forks source link

could not send message when i use UTF-16BE charset #33

Closed KimZing closed 3 years ago

KimZing commented 7 years ago

Hi,when I use default charset of utf-8 or gbk,the receiver can accept the message.but when I use UTF-16BE,the receiver do nothing.Maybe I do something wrong with my java code,but I checked my code everywhere.

hoijui commented 7 years ago

hello! :-) and thanks for the report! i guess it is because the address is also encoded using that encoding, not just the argument. now... the question is.. first of all, how would it all be with the code from the develop branch, because there are a LOT of changes there already. and second, what would be a good approach/solution for this. for one, there is the question of whether both address and argument strings use a different encoding, in the sender and in the receiver. can/should we rely on how it is in a specific case? should address always be UTF-8? OSC specification 1.0 states: "OSC-string: A sequence of non-null ASCII characters followed by a null", so it looks like anything above ASCII is not specified by the protocol. the address is also an OSC string. i see two practical solutions:

  1. try/make sure that both receiver and sender use the special encoding for both address and argument strings.
  2. use a meta protocol (one on top of OSC, which you define yourself) to communicate the encoding between sender and receiver, and then also handle encoding outside/on top of OSC. in the worst case, you would only use the default encoding with OSC, and send differently encoded strings as blobs of bytes, and encode/decode them before sending/after receiving through OSC.

if i read the code correctly, then the current JavaOSC (develop branch) uses the initiall/default encoding for the message address, always, while you may later change the encoding for argument strings. this is more accidental i would say, and i don't know if it makes sense, and if it will stay like that. but if it is like that, then surely it will either stay like this, or there will be a way to set the two encodings separately.

not sure if this is any useful.. if not, please ask again!

KimZing commented 7 years ago

Thanks for your answer, I am sure the encoding is UTF-16BE, and I have tried what you said, but not worked. But I have worked out the problem.the problem is that OSCMessage class shouldn't be use to send message, instead of using OSCPacket to contain OSCMessage. I use UDP tools to see the hexadecimal code, the generate hexadecimal coding can't match the standard of OSC correctly when i use OSCMessage, i found that the hexadecimal code is lack of "#bundle" and timestamp. Afterwards, I found the OSCPacket do the same thing and it provides a method to set parameter of OSCMessage type. The another problem is we should add header code to every parameter when we use UTF-16BE encoding, not only do in java, but so do in c#.this is my sample code:

public class OSCUtils {

    public static void sendMessage(String path, String msg) throws Exception {
            //定义发送
            OSCPortOut out = new OSCPortOut(InetAddress.getByName("127.0.0.1"), 7000);
            //发送的内容
            OSCMessage message = new OSCMessage(path);
            byte[] msgBytes = OSCUtils.getBytesFromString(msg);
            message.addArgument(msgBytes);
            OSCBundle bundle = new OSCBundle();
            bundle.addPacket(message);
            out.send(bundle);
    }

    /**
     * @param str 推送的信息
     * @return 转码后的信息
     * @throws UnsupportedEncodingException
     */
    public static byte[] getBytesFromString(String str) throws UnsupportedEncodingException {
        byte[] bytes = str.getBytes("UTF-16BE");
        byte[] allBytes = new byte[bytes.length + 4];
        allBytes[0] = 0x42;
        allBytes[1] = 0x45;
        allBytes[2] = 0x55;
        allBytes[3] = 0x43;
        for (int j = 0; j < bytes.length; j++) {
            allBytes[j + 4] = bytes[j];
        }
        return allBytes;
    }
}

It works fine, I don't know whether it should be added to the JavaOSC code as bug or feature. Thanks again! (My English is poor, maybe you read my words difficultly, i am sorry for that)

hoijui commented 7 years ago

hehe :-) yeah, you are now doing the blob method i described, good that is ok for you. no change is required for that in JavaOSC, i would say. if anyone has an encoding problem with the develop branch regarding encoding, we can look at it again. thank you for the contribution.. it might help someone else as documentation too! ride on!

hoijui commented 3 years ago

Note to self: maybe we should make a test-case for that; apart from that, it could be closed.