Advertisement

C++ to Java socket data transfer problem

Started by November 07, 2005 03:23 PM
5 comments, last by stipperdoo 19 years, 3 months ago
I am attempting to pass data between a C++ Client and a Java Server using Winsock and java NIO. It appears to work ok until I output the data sent, which results in something strage... Here is some code: C++ side: ========= SendData(Main.Sock, "0mikeclient"); int SendData(SOCKET sock, char * lpszData) { return send(sock, lpszData, strlen(lpszData), 0); } Java side: ========== SocketChannel sc = (SocketChannel)key.channel(); ByteBuffer inputBuffer = ByteBuffer.allocate( 1024 ); inputBuffer.clear(); System.out.println("NW Subsys: State of input buffer before read: "+inputBuffer); sc.read(inputBuffer); System.out.println("NW Subsys: State of input buffer after read: "+inputBuffer); CharBuffer tempCharBuffer = inputBuffer.asCharBuffer(); System.out.println("NW Subsys: Contents of read buffer: "+tempCharBuffer.toString()); Here is the output: NW Subsys: State of input buffer before read: java.nio.HeapByteBuffer[pos=0 lim= 1024 cap=1024] NW Subsys: State of input buffer after read: java.nio.HeapByteBuffer[pos=11 lim= 1024 cap=1024] NW Subsys: Contents of input buffer: ??????? Host: no helper avaiable to process event type: null Event sent: null from java.nio.channels.SocketChannel[connected local=/127.0.0.1 :1234 remote=/127.0.0.1:1435] --- If you look at the value of 'pos' in the before and after read output, you can see that the right number of bytes appears to have been sent, but the contects are just a bunch of question marks. Any thoughts? Thanks, Stip
And... if I spit out the first several bytes of the buffer:

byte b = buffer.get();
System.out.println("EventParser: first byte: "+b);
b = buffer.get();
System.out.println("EventParser: next byte: "+b);

I get the following results:

EventParser: first byte: 58
EventParser: next byte: 32
EventParser: next byte: 66
EventParser: next byte: 97
EventParser: next byte: 99

...Stip
Advertisement
Take a look at the Javadocs for java.nio.ByteBuffer.asCharBuffer(). The relevant bit for your situation is this:

Quote:
The content of the new buffer will start at this buffer's current position.


Try adding a call to Buffer.rewind() before getting the CharBuffer:

inputBuffer.rewind(); // set the buffer pos to 0 and the limit to the current posCharBuffer tempCharBuffer = inputBuffer.asCharBuffer();System.out.println("NW Subsys: Contents of read buffer: "+tempCharBuffer.toString());


But really, when pulling strings from the net, you probably should be using an instance of java.nio.charset.Charset to decode the string rather than pulling it straight from a CharBuffer view:

inputBuffer.rewind();Charset cs = Charset.forName("ASCII");String decoded = cs.decode(inputBuffer).toString();System.out.println(decoded);


Take a look at Adam Martin's NIO tutorial for more info.

As an aside, take a look at the forum FAQ for using source tags. Look in the "Code" section. It makes reading chunks of source code so much easier.
Thanks for the advice. Creating the CharBuffer view before reading the ByteBuffer worked.

Additionally, a closer look at the types revealed that C++ chars are one byte, and Java chars are two bytes. Therefore, when passing a string from C++ to Java, you have to cast each byte position to a char type, and when passing the string from Java to C++, you have to cast each char to a single byte.

Is there an easy way to do this rather than explicitly casting each array location, i.e. casting arrays in either C++ or Java?

...Stip
Use wchar_t in C++ (which are two bytes on Windows, but four bytes on Linux).

Then you can use mbstowcs(), std::wstring, or whatever other standard library function strikes your fancy.
enum Bool { True, False, FileNotFound };
Quote:
Original post by stipperdooIs there an easy way to do this rather than explicitly casting each array location, i.e. casting arrays in either C++ or Java?


Did you use the java.nio.charset.Charset class like I showed you? Instantiating one with the "ASCII" character set should work if you are going to use single byte strings on the C++ side. Use the decode method on the strings you receive and encode on the strings you send.
Advertisement
The Charset works great. And I just decode and encode on the Java side and I don't have to do anything on the C++ side. Even better! Thanks for the help.

...Stip

This topic is closed to new replies.

Advertisement