Reputation: 4585
This is what I've tried:
Server:
import java.net.InetSocketAddress;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
public class JavaApplication12 {
public static void main(String[] args) throws Exception{
Charset charset = Charset.forName("ISO-8859-1");
ServerSocketChannel s = ServerSocketChannel.open();
s.configureBlocking(true);
s.socket().bind(new InetSocketAddress(1024));
CharBuffer c = CharBuffer.wrap("Hello from server!");
System.out.println("writing " + c);
ByteBuffer b = charset.encode(c);
SocketChannel sc = s.accept();
sc.configureBlocking(true);
b.flip();
int a = sc.write(b);
sc.close();
s.close();
System.out.println("wrote " + a);
}
}
Client:
import java.net.InetSocketAddress;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
public class JavaApplication11 {
public static void main(String[] args) throws Exception {
Charset charset = Charset.forName("ISO-8859-1");
SocketChannel sc = SocketChannel.open(new InetSocketAddress("127.0.0.1", 1024));
sc.configureBlocking(true);
ByteBuffer b = ByteBuffer.allocate(32);
b.flip();
int a = sc.read(b);
sc.close();
b.flip();
CharBuffer c = charset.decode(b);
c.flip();
System.out.println("Got " + c);
System.out.println("read " + a );
}
}
The other side seems to just get a very long and empty string, and I can't figure out what I'm doing wrong.
Update: I've updated my code, and found that the server is writing 0 bytes. There are bytes to write, so why isn't sc.write()
writing anything?
Update 2: With Vishal's help we finally have a working solution:
Server:
Charset charset = Charset.forName("ISO-8859-1");
ServerSocketChannel s = ServerSocketChannel.open();
s.configureBlocking(true);
s.socket().bind(new InetSocketAddress(1024));
CharBuffer c = CharBuffer.wrap("Hello from server!");
ByteBuffer b = charset.encode(c);
SocketChannel sc = s.accept();
sc.configureBlocking(true);
b.compact();
b.flip();
int a = sc.write(b);
sc.close();
s.close();
System.out.println("wrote " + a);
Client:
Charset charset = Charset.forName("ISO-8859-1");
SocketChannel sc = SocketChannel.open(new InetSocketAddress("127.0.0.1", 1024));
sc.configureBlocking(true);
ByteBuffer b = ByteBuffer.allocate(32);
int a = sc.read(b);
sc.close();
b.flip();
CharBuffer c = charset.decode(b);
System.out.println("Got " + c);
Upvotes: 2
Views: 3120
Reputation: 13066
Buffer.flip() method switches a Buffer from writing mode to reading mode. Calling
flip()
sets the position back to 0, and sets the limit to where position just was.
i.e the position now marks the reading position, and limit marks how many bytes, chars etc. were written into the buffer - the limit of how many bytes, chars etc. that can be read
If you see at documentation of Buffer.flip()
it states that:
After a sequence of channel-read or
put
operations, invoke this method to prepare for a sequence of channel-write or relative get operations.
And further is states that:
This method is often used in conjunction with the
compact
method when transferring data from one place to another.
In your case , put
operation is not used for ByteBuffer
creation. So you would have to call compact
method before the flip is called.
ByteBuffer's
compact() method stays that:
The bytes between the buffer's current position and its limit, if any, are copied to the beginning of the buffer. That is, the byte at index p = position() is copied to index zero, the byte at index p + 1 is copied to index one, and so forth until the byte at index limit() - 1 is copied to index n = limit() - 1 - p. The buffer's position is then set to n+1 and its limit is set to its capacity. The mark, if defined, is discarded.
The buffer's position is set to the number of bytes copied, rather than to zero, so that an invocation of this method can be followed immediately by an invocation of another relative put method. Invoke this method after writing data from a buffer in case the write was incomplete.
In your code at server side Before flip()
is called the position was itself 0 . So to set the position
to number bytes written to b
You would have to call compact()
method before b.flip()
is called so that the b.flip()
sets the limit
to the previous position
which is the number of bytes wrote to ByteBuffer
, and set the position
to 0
.
Consequently Your Server Code should be like this:
import java.net.InetSocketAddress;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
public class JavaApplication12 {
public static void main(String[] args) throws Exception{
Charset charset = Charset.forName("ISO-8859-1");
ServerSocketChannel s = ServerSocketChannel.open();
s.configureBlocking(true);
s.socket().bind(new InetSocketAddress(1024));
CharBuffer c = CharBuffer.wrap("Hello from server!");
System.out.println("writing " + c);
ByteBuffer b = charset.encode(c);
System.out.println(new String(b.array()));
SocketChannel sc = s.accept();
//sc.configureBlocking(true);
b.compact();
System.out.println(b.capacity() + " "+ b.position() + " " + b.limit());
b.flip();
System.out.println(b.capacity() + " "+ b.position() + " " + b.limit());
int a = 0;
while (b.hasRemaining())
{
a += sc.write(b);
}
sc.close();
s.close();
System.out.println("wrote " + a);
}
}
LikeWise , At client side your code should be like this:
import java.net.InetSocketAddress;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
public class JavaApplication11 {
public static void main(String[] args) throws Exception {
Charset charset = Charset.forName("ISO-8859-1");
SocketChannel sc = SocketChannel.open(new InetSocketAddress("127.0.0.1", 1024));
sc.configureBlocking(true);
ByteBuffer b = ByteBuffer.allocate(32);
//b.flip();//Don't flip the ByteBuffer here because it sets the position to 0 and limit to 0 also. Hence no read.
int a = sc.read(b);
sc.close();
b.flip();//sets the Position to 0 and limit to the number of bytes to be read.
CharBuffer c = charset.decode(b);
//c.flip();//Don't flip the ChharBuffer. Because it is setting the position to zero and limit to previous position i.e zero
System.out.println("Got " + c);
System.out.println("read " + a );
}
}
Note:I have put comment on lines where you made mistakes.
Upvotes: 3
Reputation: 310850
You need to flip() the buffer between the read() and the decode().
Upvotes: 0